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;
5325 DSAStackTy::DSAVarData
Data = Stack->getTopDSA(VD,
false);
5328 diag::err_omp_expected_private_copy_for_allocate);
5331 VarDecl *PrivateVD = DeclToCopy[VD];
5333 AllocatorKind, AC->getAllocator()))
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 ||
15621 CKind == OMPC_allocate) &&
15627 if (CKind == OMPC_collapse &&
DSAStack->getAssociatedLoops() == 1)
15629 else if (CKind == OMPC_ordered)
15664 DSAStackTy *Stack) {
15665 if (!Stack->getOMPAllocatorHandleT().isNull())
15672 S.
Diag(
Loc, diag::err_omp_implied_type_not_found)
15673 <<
"omp_allocator_handle_t";
15678 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
15681 bool ErrorFound =
false;
15682 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
15683 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
15684 StringRef Allocator =
15685 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
15687 auto *VD = dyn_cast_or_null<ValueDecl>(
15707 Stack->setAllocator(AllocatorKind, Res.
get());
15710 S.
Diag(
Loc, diag::err_omp_implied_type_not_found)
15711 <<
"omp_allocator_handle_t";
15728 if (Allocator.isInvalid())
15731 Allocator.get(),
DSAStack->getOMPAllocatorHandleT(),
15734 if (Allocator.isInvalid())
15760 Expr *NumForLoops) {
15766 if (NumForLoops && LParenLoc.
isValid()) {
15771 NumForLoops = NumForLoopsResult.
get();
15773 NumForLoops =
nullptr;
15777 NumForLoops ?
DSAStack->getAssociatedLoops() : 0,
15778 StartLoc, LParenLoc, EndLoc);
15779 DSAStack->setOrderedRegion(
true, NumForLoops, Clause);
15790 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15792 case OMPC_proc_bind:
15794 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15796 case OMPC_atomic_default_mem_order:
15799 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15803 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15807 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15811 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15815 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15817 case OMPC_severity:
15820 LParenLoc, EndLoc);
15824 case OMPC_num_threads:
15828 case OMPC_allocator:
15829 case OMPC_collapse:
15830 case OMPC_schedule:
15832 case OMPC_firstprivate:
15833 case OMPC_lastprivate:
15835 case OMPC_reduction:
15836 case OMPC_task_reduction:
15837 case OMPC_in_reduction:
15841 case OMPC_copyprivate:
15845 case OMPC_mergeable:
15846 case OMPC_threadprivate:
15847 case OMPC_allocate:
15864 case OMPC_num_teams:
15865 case OMPC_thread_limit:
15866 case OMPC_priority:
15867 case OMPC_grainsize:
15869 case OMPC_num_tasks:
15871 case OMPC_dist_schedule:
15872 case OMPC_defaultmap:
15877 case OMPC_use_device_ptr:
15878 case OMPC_use_device_addr:
15879 case OMPC_is_device_ptr:
15880 case OMPC_has_device_addr:
15881 case OMPC_unified_address:
15882 case OMPC_unified_shared_memory:
15883 case OMPC_reverse_offload:
15884 case OMPC_dynamic_allocators:
15885 case OMPC_device_type:
15887 case OMPC_nontemporal:
15889 case OMPC_novariants:
15890 case OMPC_nocontext:
15892 case OMPC_inclusive:
15893 case OMPC_exclusive:
15894 case OMPC_uses_allocators:
15895 case OMPC_affinity:
15899 llvm_unreachable(
"Clause is not allowed.");
15908 llvm::raw_svector_ostream Out(Buffer);
15909 unsigned Skipped = Exclude.size();
15910 for (
unsigned I =
First; I <
Last; ++I) {
15911 if (llvm::is_contained(Exclude, I)) {
15916 if (I + Skipped + 2 ==
Last)
15918 else if (I + Skipped + 1 !=
Last)
15921 return std::string(Out.str());
15929 if (Kind == OMP_DEFAULT_unknown) {
15930 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15932 unsigned(OMP_DEFAULT_unknown))
15933 << getOpenMPClauseName(OMPC_default);
15938 case OMP_DEFAULT_none:
15939 DSAStack->setDefaultDSANone(KindKwLoc);
15941 case OMP_DEFAULT_shared:
15942 DSAStack->setDefaultDSAShared(KindKwLoc);
15944 case OMP_DEFAULT_firstprivate:
15945 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
15947 case OMP_DEFAULT_private:
15948 DSAStack->setDefaultDSAPrivate(KindKwLoc);
15951 llvm_unreachable(
"DSA unexpected in OpenMP default clause");
15963 if (Kind == OMP_PROC_BIND_unknown) {
15964 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15966 unsigned(OMP_PROC_BIND_master),
15969 ? OMP_PROC_BIND_primary
15970 : OMP_PROC_BIND_spread) +
15972 << getOpenMPClauseName(OMPC_proc_bind);
15975 if (Kind == OMP_PROC_BIND_primary &&
getLangOpts().OpenMP < 51)
15976 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15978 unsigned(OMP_PROC_BIND_master),
15980 unsigned(OMP_PROC_BIND_spread) + 1)
15981 << getOpenMPClauseName(OMPC_proc_bind);
15990 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15992 OMPC_atomic_default_mem_order, 0,
15994 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
15998 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16007 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16010 << getOpenMPClauseName(OMPC_at);
16014 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16023 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16026 << getOpenMPClauseName(OMPC_severity);
16037 assert(ME &&
"NULL expr in Message clause");
16038 if (!isa<StringLiteral>(ME)) {
16040 << getOpenMPClauseName(OMPC_message);
16051 if (Kind != OMPC_ORDER_concurrent ||
16056 "OMPC_ORDER_unknown not greater than 0");
16058 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16062 << getOpenMPClauseName(OMPC_order);
16067 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16071 << getOpenMPClauseName(OMPC_order);
16073 DSAStack->setRegionHasOrderConcurrent(
true);
16076 unsigned existingFlags =
DSAStack->getCurScope()->getFlags();
16077 DSAStack->getCurScope()->setFlags(existingFlags |
16083 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
16092 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16094 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16095 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16097 Except.push_back(OMPC_DEPEND_inoutset);
16098 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16101 << getOpenMPClauseName(OMPC_update);
16105 KindKwLoc, Kind, EndLoc);
16114 for (
Expr *&SizeExpr : SanitizedSizeExprs) {
16124 QualType SizeTy = SizeExpr->getType();
16153 if (!SizeExpr->isInstantiationDependent() && !IsValid)
16154 SizeExpr =
nullptr;
16158 SanitizedSizeExprs);
16165 size_t NumLoops = PermExprs.size();
16167 llvm::append_range(SanitizedPermExprs, PermExprs);
16169 for (
Expr *&PermExpr : SanitizedPermExprs) {
16172 if (!PermExpr || PermExpr->isInstantiationDependent())
16175 llvm::APSInt PermVal;
16178 bool IsValid = PermEvalExpr.
isUsable();
16180 PermExpr = PermEvalExpr.
get();
16182 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
16186 diag::err_omp_interchange_permutation_value_range)
16187 << NumLoops << ExprRange;
16191 if (!PermExpr->isInstantiationDependent() && !IsValid)
16192 PermExpr =
nullptr;
16196 EndLoc, SanitizedPermExprs);
16212 FactorExpr, OMPC_partial,
true);
16215 FactorExpr = FactorResult.
get();
16230 LParenLoc, EndLoc);
16240 case OMPC_schedule:
16241 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16242 assert(Argument.size() == NumberOfElements &&
16243 ArgumentLoc.size() == NumberOfElements);
16248 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16249 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16252 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16254 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16257 case OMPC_dist_schedule:
16260 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16262 case OMPC_defaultmap:
16263 enum { Modifier, DefaultmapKind };
16267 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16271 enum { OrderModifier, OrderKind };
16275 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
16278 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16281 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16283 case OMPC_grainsize:
16284 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16285 "Modifier for grainsize clause and its location are expected.");
16288 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16290 case OMPC_num_tasks:
16291 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16292 "Modifier for num_tasks clause and its location are expected.");
16295 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16298 case OMPC_num_threads:
16302 case OMPC_allocator:
16303 case OMPC_collapse:
16305 case OMPC_proc_bind:
16307 case OMPC_firstprivate:
16308 case OMPC_lastprivate:
16310 case OMPC_reduction:
16311 case OMPC_task_reduction:
16312 case OMPC_in_reduction:
16316 case OMPC_copyprivate:
16320 case OMPC_mergeable:
16321 case OMPC_threadprivate:
16322 case OMPC_allocate:
16339 case OMPC_num_teams:
16340 case OMPC_thread_limit:
16341 case OMPC_priority:
16348 case OMPC_use_device_ptr:
16349 case OMPC_use_device_addr:
16350 case OMPC_is_device_ptr:
16351 case OMPC_has_device_addr:
16352 case OMPC_unified_address:
16353 case OMPC_unified_shared_memory:
16354 case OMPC_reverse_offload:
16355 case OMPC_dynamic_allocators:
16356 case OMPC_atomic_default_mem_order:
16357 case OMPC_device_type:
16359 case OMPC_nontemporal:
16361 case OMPC_severity:
16364 case OMPC_novariants:
16365 case OMPC_nocontext:
16367 case OMPC_inclusive:
16368 case OMPC_exclusive:
16369 case OMPC_uses_allocators:
16370 case OMPC_affinity:
16374 llvm_unreachable(
"Clause is not allowed.");
16385 Excluded.push_back(M2);
16386 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16387 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16388 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16389 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16390 S.
Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16395 << getOpenMPClauseName(OMPC_schedule);
16413 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16414 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16415 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16416 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16417 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16423 std::string Values;
16433 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16434 << Values << getOpenMPClauseName(OMPC_schedule);
16442 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16443 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16444 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16445 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16446 diag::err_omp_schedule_nonmonotonic_static);
16449 Expr *ValExpr = ChunkSize;
16450 Stmt *HelperValStmt =
nullptr;
16461 ValExpr = Val.
get();
16466 if (std::optional<llvm::APSInt>
Result =
16468 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
16469 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16474 DSAStack->getCurrentDirective(), OMPC_schedule,
16478 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16479 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16487 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16504 case OMPC_mergeable:
16552 case OMPC_unified_address:
16555 case OMPC_unified_shared_memory:
16558 case OMPC_reverse_offload:
16561 case OMPC_dynamic_allocators:
16575 case OMPC_ompx_bare:
16580 case OMPC_num_threads:
16584 case OMPC_allocator:
16585 case OMPC_collapse:
16586 case OMPC_schedule:
16588 case OMPC_firstprivate:
16589 case OMPC_lastprivate:
16591 case OMPC_reduction:
16592 case OMPC_task_reduction:
16593 case OMPC_in_reduction:
16597 case OMPC_copyprivate:
16599 case OMPC_proc_bind:
16600 case OMPC_threadprivate:
16601 case OMPC_allocate:
16607 case OMPC_num_teams:
16608 case OMPC_thread_limit:
16609 case OMPC_priority:
16610 case OMPC_grainsize:
16611 case OMPC_num_tasks:
16613 case OMPC_dist_schedule:
16614 case OMPC_defaultmap:
16619 case OMPC_use_device_ptr:
16620 case OMPC_use_device_addr:
16621 case OMPC_is_device_ptr:
16622 case OMPC_has_device_addr:
16623 case OMPC_atomic_default_mem_order:
16624 case OMPC_device_type:
16626 case OMPC_nontemporal:
16629 case OMPC_severity:
16631 case OMPC_novariants:
16632 case OMPC_nocontext:
16634 case OMPC_inclusive:
16635 case OMPC_exclusive:
16636 case OMPC_uses_allocators:
16637 case OMPC_affinity:
16639 case OMPC_ompx_dyn_cgroup_mem:
16641 llvm_unreachable(
"Clause is not allowed.");
16700 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
16781 if (!
hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
16782 StringRef
Expected =
"'init', 'use', 'destroy', or 'nowait'";
16783 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
16784 <<
Expected << getOpenMPDirectiveName(OMPD_interop);
16797 bool HasInitClause =
false;
16798 bool IsTargetSync =
false;
16802 if (
const auto *InitClause = dyn_cast<OMPInitClause>(
C)) {
16803 HasInitClause =
true;
16804 if (InitClause->getIsTargetSync())
16805 IsTargetSync =
true;
16806 }
else if (
const auto *DC = dyn_cast<OMPDependClause>(
C)) {
16810 if (DependClause && HasInitClause && !IsTargetSync) {
16811 Diag(DependClause->
getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
16825 if (ClauseKind == OMPC_init) {
16826 auto *
E = cast<OMPInitClause>(
C)->getInteropVar();
16828 }
else if (ClauseKind == OMPC_use) {
16829 auto *
E = cast<OMPUseClause>(
C)->getInteropVar();
16831 }
else if (ClauseKind == OMPC_destroy) {
16832 auto *
E = cast<OMPDestroyClause>(
C)->getInteropVar();
16837 if (!InteropVars.insert(
DeclResult.first).second) {
16838 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
16854 Expr *RefExpr = InteropVarExpr;
16857 false,
"omp_interop_t");
16868 bool HasError =
false;
16874 if (
const auto *TD = dyn_cast<TypeDecl>(ND)) {
16875 InteropType =
QualType(TD->getTypeForDecl(), 0);
16884 SemaRef.
Diag(VarLoc, diag::err_omp_implied_type_not_found)
16885 <<
"omp_interop_t";
16891 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
16897 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
16899 SemaRef.
Diag(VarLoc, diag::err_omp_interop_variable_expected)
16921 if (isa<StringLiteral>(
E))
16928 StartLoc, LParenLoc, VarLoc, EndLoc);
16941 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16950 DSAStack->getCurrentDirective() == OMPD_depobj) {
16951 Diag(StartLoc, diag::err_omp_expected_clause_argument)
16952 << getOpenMPClauseName(OMPC_destroy)
16953 << getOpenMPDirectiveName(OMPD_depobj);
16969 Stmt *HelperValStmt =
nullptr;
16972 !
Condition->isInstantiationDependent() &&
16973 !
Condition->containsUnexpandedParameterPack()) {
16983 if (CaptureRegion != OMPD_unknown &&
16986 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16987 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
16993 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17001 Stmt *HelperValStmt =
nullptr;
17004 !
Condition->isInstantiationDependent() &&
17005 !
Condition->containsUnexpandedParameterPack()) {
17015 if (CaptureRegion != OMPD_unknown &&
17018 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17019 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17025 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17032 Expr *ValExpr = ThreadID;
17033 Stmt *HelperValStmt =
nullptr;
17038 if (CaptureRegion != OMPD_unknown &&
17041 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17042 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
17047 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17058 int ExtraModifier =
Data.ExtraModifier;
17065 case OMPC_firstprivate:
17068 case OMPC_lastprivate:
17070 "Unexpected lastprivate modifier.");
17073 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17078 case OMPC_reduction:
17080 "Unexpected lastprivate modifier.");
17083 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17084 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
17086 case OMPC_task_reduction:
17088 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17089 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
17091 case OMPC_in_reduction:
17093 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17094 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId);
17098 "Unexpected linear modifier.");
17100 VarList,
Data.DepModOrTailExpr, StartLoc, LParenLoc,
17102 ColonLoc,
Data.StepModifierLoc, EndLoc);
17106 LParenLoc, ColonLoc, EndLoc);
17111 case OMPC_copyprivate:
17119 "Unexpected depend modifier.");
17122 ColonLoc,
Data.OmpAllMemoryLoc},
17123 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17127 "Unexpected map modifier.");
17129 Data.IteratorExpr,
Data.MapTypeModifiers,
Data.MapTypeModifiersLoc,
17130 Data.ReductionOrMapperIdScopeSpec,
Data.ReductionOrMapperId,
17132 ExtraModifierLoc, ColonLoc, VarList, Locs);
17137 Data.ReductionOrMapperIdScopeSpec,
17138 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17142 Data.ReductionOrMapperIdScopeSpec,
17143 Data.ReductionOrMapperId, ColonLoc, VarList,
17146 case OMPC_use_device_ptr:
17149 case OMPC_use_device_addr:
17152 case OMPC_is_device_ptr:
17155 case OMPC_has_device_addr:
17158 case OMPC_allocate: {
17162 if (!
Data.AllocClauseModifiers.empty()) {
17163 assert(
Data.AllocClauseModifiers.size() <= 2 &&
17164 "More allocate modifiers than expected");
17165 Modifier1 =
Data.AllocClauseModifiers[0];
17166 Modifier1Loc =
Data.AllocClauseModifiersLoc[0];
17167 if (
Data.AllocClauseModifiers.size() == 2) {
17168 Modifier2 =
Data.AllocClauseModifiers[1];
17169 Modifier2Loc =
Data.AllocClauseModifiersLoc[1];
17173 Data.DepModOrTailExpr,
Data.AllocateAlignment, Modifier1, Modifier1Loc,
17174 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
17178 case OMPC_nontemporal:
17181 case OMPC_inclusive:
17184 case OMPC_exclusive:
17187 case OMPC_affinity:
17189 Data.DepModOrTailExpr, VarList);
17191 case OMPC_doacross:
17194 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
17196 case OMPC_num_teams:
17199 case OMPC_thread_limit:
17205 case OMPC_num_threads:
17209 case OMPC_allocator:
17210 case OMPC_collapse:
17212 case OMPC_proc_bind:
17213 case OMPC_schedule:
17217 case OMPC_mergeable:
17218 case OMPC_threadprivate:
17232 case OMPC_priority:
17233 case OMPC_grainsize:
17235 case OMPC_num_tasks:
17237 case OMPC_dist_schedule:
17238 case OMPC_defaultmap:
17241 case OMPC_unified_address:
17242 case OMPC_unified_shared_memory:
17243 case OMPC_reverse_offload:
17244 case OMPC_dynamic_allocators:
17245 case OMPC_atomic_default_mem_order:
17246 case OMPC_device_type:
17250 case OMPC_severity:
17253 case OMPC_novariants:
17254 case OMPC_nocontext:
17256 case OMPC_uses_allocators:
17260 llvm_unreachable(
"Clause is not allowed.");
17291 bool IsImplicitClause =
17293 for (
Expr *RefExpr : VarList) {
17294 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
17297 Expr *SimpleRefExpr = RefExpr;
17301 Vars.push_back(RefExpr);
17302 PrivateCopies.push_back(
nullptr);
17309 auto *VD = dyn_cast<VarDecl>(
D);
17315 diag::err_omp_private_incomplete_type))
17317 Type =
Type.getNonReferenceType();
17337 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17338 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17339 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17340 << getOpenMPClauseName(OMPC_private);
17349 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17350 << getOpenMPClauseName(OMPC_private) <<
Type
17351 << getOpenMPDirectiveName(CurrDir);
17352 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17355 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17370 CurrDir == OMPD_target) {
17372 if (
DSAStack->checkMappableExprComponentListsForDecl(
17376 ConflictKind = WhereFoundClauseKind;
17379 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17380 << getOpenMPClauseName(OMPC_private)
17381 << getOpenMPClauseName(ConflictKind)
17382 << getOpenMPDirectiveName(CurrDir);
17401 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
17410 auto *FD = dyn_cast<FieldDecl>(
D);
17414 RefExpr->getExprLoc());
17418 if (!IsImplicitClause)
17419 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17421 ? RefExpr->IgnoreParens()
17423 PrivateCopies.push_back(VDPrivateRefExpr);
17430 Vars, PrivateCopies);
17441 bool IsImplicitClause =
17445 for (
Expr *RefExpr : VarList) {
17446 assert(RefExpr &&
"NULL expr in OpenMP firstprivate clause.");
17449 Expr *SimpleRefExpr = RefExpr;
17453 Vars.push_back(RefExpr);
17454 PrivateCopies.push_back(
nullptr);
17455 Inits.push_back(
nullptr);
17461 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17463 auto *VD = dyn_cast<VarDecl>(
D);
17469 diag::err_omp_firstprivate_incomplete_type))
17471 Type =
Type.getNonReferenceType();
17481 DSAStackTy::DSAVarData TopDVar;
17482 if (!IsImplicitClause) {
17483 DSAStackTy::DSAVarData DVar =
17495 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17497 DVar.CKind != OMPC_lastprivate) &&
17499 Diag(ELoc, diag::err_omp_wrong_dsa)
17500 << getOpenMPClauseName(DVar.CKind)
17501 << getOpenMPClauseName(OMPC_firstprivate);
17517 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17518 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17519 Diag(ELoc, diag::err_omp_wrong_dsa)
17520 << getOpenMPClauseName(DVar.CKind)
17521 << getOpenMPClauseName(OMPC_firstprivate);
17545 DVar =
DSAStack->getImplicitDSA(
D,
true);
17546 if (DVar.CKind != OMPC_shared &&
17549 DVar.DKind == OMPD_unknown)) {
17550 Diag(ELoc, diag::err_omp_required_access)
17551 << getOpenMPClauseName(OMPC_firstprivate)
17552 << getOpenMPClauseName(OMPC_shared);
17572 return C == OMPC_reduction && !AppliedToPointee;
17580 if (DVar.CKind == OMPC_reduction &&
17584 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
17585 << getOpenMPDirectiveName(DVar.DKind);
17601 CurrDir == OMPD_target) {
17603 if (
DSAStack->checkMappableExprComponentListsForDecl(
17608 ConflictKind = WhereFoundClauseKind;
17611 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17612 << getOpenMPClauseName(OMPC_firstprivate)
17613 << getOpenMPClauseName(ConflictKind)
17614 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
17624 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17625 << getOpenMPClauseName(OMPC_firstprivate) <<
Type
17626 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
17627 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17630 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17639 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
17645 Expr *VDInitRefExpr =
nullptr;
17655 ElemType,
".firstprivate.temp");
17670 ".firstprivate.temp");
17672 RefExpr->getExprLoc());
17678 if (IsImplicitClause) {
17679 Diag(RefExpr->getExprLoc(),
17680 diag::note_omp_task_predetermined_firstprivate_here);
17687 RefExpr->getExprLoc());
17690 if (TopDVar.CKind == OMPC_lastprivate) {
17691 Ref = TopDVar.PrivateCopy;
17693 auto *FD = dyn_cast<FieldDecl>(
D);
17698 RefExpr->getExprLoc());
17702 ExprCaptures.push_back(Ref->
getDecl());
17705 if (!IsImplicitClause)
17706 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
17708 ? RefExpr->IgnoreParens()
17710 PrivateCopies.push_back(VDPrivateRefExpr);
17711 Inits.push_back(VDInitRefExpr);
17718 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
17727 assert(ColonLoc.
isValid() &&
"Colon location must be valid.");
17728 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
17731 << getOpenMPClauseName(OMPC_lastprivate);
17741 for (
Expr *RefExpr : VarList) {
17742 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
17745 Expr *SimpleRefExpr = RefExpr;
17749 Vars.push_back(RefExpr);
17750 SrcExprs.push_back(
nullptr);
17751 DstExprs.push_back(
nullptr);
17752 AssignmentOps.push_back(
nullptr);
17759 auto *VD = dyn_cast<VarDecl>(
D);
17765 diag::err_omp_lastprivate_incomplete_type))
17767 Type =
Type.getNonReferenceType();
17784 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
17785 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
17788 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17802 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17803 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
17805 DVar.CKind != OMPC_firstprivate) &&
17806 (DVar.CKind != OMPC_private || DVar.RefExpr !=
nullptr)) {
17807 Diag(ELoc, diag::err_omp_wrong_dsa)
17808 << getOpenMPClauseName(DVar.CKind)
17809 << getOpenMPClauseName(OMPC_lastprivate);
17820 DSAStackTy::DSAVarData TopDVar = DVar;
17824 DVar =
DSAStack->getImplicitDSA(
D,
true);
17825 if (DVar.CKind != OMPC_shared) {
17826 Diag(ELoc, diag::err_omp_required_access)
17827 << getOpenMPClauseName(OMPC_lastprivate)
17828 << getOpenMPClauseName(OMPC_shared);
17844 Type.getUnqualifiedType(),
".lastprivate.src",
17855 PseudoDstExpr, PseudoSrcExpr);
17865 if (TopDVar.CKind == OMPC_firstprivate) {
17866 Ref = TopDVar.PrivateCopy;
17870 ExprCaptures.push_back(Ref->
getDecl());
17872 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
17880 SimpleRefExpr, RefRes.
get());
17883 ExprPostUpdates.push_back(
17887 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
17889 ? RefExpr->IgnoreParens()
17891 SrcExprs.push_back(PseudoSrcExpr);
17892 DstExprs.push_back(PseudoDstExpr);
17893 AssignmentOps.push_back(AssignmentOp.
get());
17900 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
17901 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
17911 for (
Expr *RefExpr : VarList) {
17912 assert(RefExpr &&
"NULL expr in OpenMP lastprivate clause.");
17915 Expr *SimpleRefExpr = RefExpr;
17919 Vars.push_back(RefExpr);
17925 auto *VD = dyn_cast<VarDecl>(
D);
17933 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
17934 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
17936 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17937 << getOpenMPClauseName(OMPC_shared);
17946 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
17948 ? RefExpr->IgnoreParens()
17960class DSARefChecker :
public StmtVisitor<DSARefChecker, bool> {
17965 if (
auto *VD = dyn_cast<VarDecl>(
E->getDecl())) {
17966 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD,
false);
17967 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
17969 if (DVar.CKind != OMPC_unknown)
17971 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
17978 return DVarPrivate.CKind != OMPC_unknown;
17982 bool VisitStmt(
Stmt *S) {
17983 for (
Stmt *Child : S->children()) {
17984 if (Child && Visit(Child))
17989 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
17996class TransformExprToCaptures :
public TreeTransform<TransformExprToCaptures> {
18003 : BaseTransform(SemaRef),
Field(
FieldDecl), CapturedExpr(nullptr) {}
18007 E->getMemberDecl() == Field) {
18009 return CapturedExpr;
18011 return BaseTransform::TransformMemberExpr(
E);
18013 DeclRefExpr *getCapturedExpr() {
return CapturedExpr; }
18017template <
typename T,
typename U>
18020 for (
U &
Set : Lookups) {
18021 for (
auto *
D :
Set) {
18022 if (
T Res = Gen(cast<ValueDecl>(
D)))
18037 auto ND = cast<NamedDecl>(RD);
18055 AssociatedClasses);
18068 for (
auto *NS : AssociatedNamespaces) {
18081 for (
auto *
D : R) {
18082 auto *Underlying =
D;
18083 if (
auto *USD = dyn_cast<UsingShadowDecl>(
D))
18084 Underlying = USD->getTargetDecl();
18086 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
18087 !isa<OMPDeclareMapperDecl>(Underlying))
18094 if (
auto *USD = dyn_cast<UsingShadowDecl>(
D))
18095 Underlying = USD->getTargetDecl();
18097 Lookups.emplace_back();
18098 Lookups.back().addDecl(Underlying);
18118 S = S->getParent();
18119 }
while (S && !S->isDeclScope(
D));
18121 S = S->getParent();
18122 Lookups.emplace_back();
18123 Lookups.back().append(Lookup.
begin(), Lookup.
end());
18126 }
else if (
auto *ULE =
18127 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18129 Decl *PrevD =
nullptr;
18133 else if (
auto *DRD = dyn_cast<OMPDeclareReductionDecl>(
D))
18134 Lookups.back().addDecl(DRD);
18141 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
18142 return !D->isInvalidDecl() &&
18143 (D->getType()->isDependentType() ||
18144 D->getType()->isInstantiationDependentType() ||
18145 D->getType()->containsUnexpandedParameterPack());
18158 true, ResSet.
begin(), ResSet.
end(),
false,
18180 TyRec->getDecl()->getDefinition()) {
18183 if (Lookup.
empty()) {
18184 Lookups.emplace_back();
18185 Lookups.back().append(Lookup.
begin(), Lookup.
end());
18192 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18202 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18227 if (ReductionIdScopeSpec.
isSet()) {
18228 SemaRef.
Diag(
Loc, diag::err_omp_not_resolved_reduction_identifier)
18237struct ReductionData {
18262 unsigned RedModifier = 0;
18263 ReductionData() =
delete;
18265 ReductionData(
unsigned Size,
unsigned Modifier = 0) : RedModifier(Modifier) {
18266 Vars.reserve(Size);
18267 Privates.reserve(Size);
18268 LHSs.reserve(Size);
18269 RHSs.reserve(Size);
18270 ReductionOps.reserve(Size);
18271 if (RedModifier == OMPC_REDUCTION_inscan) {
18272 InscanCopyOps.reserve(Size);
18273 InscanCopyArrayTemps.reserve(Size);
18274 InscanCopyArrayElems.reserve(Size);
18276 TaskgroupDescriptors.reserve(Size);
18277 ExprCaptures.reserve(Size);
18278 ExprPostUpdates.reserve(Size);
18282 void push(
Expr *Item,
Expr *ReductionOp) {
18283 Vars.emplace_back(Item);
18284 Privates.emplace_back(
nullptr);
18285 LHSs.emplace_back(
nullptr);
18286 RHSs.emplace_back(
nullptr);
18287 ReductionOps.emplace_back(ReductionOp);
18288 TaskgroupDescriptors.emplace_back(
nullptr);
18289 if (RedModifier == OMPC_REDUCTION_inscan) {
18290 InscanCopyOps.push_back(
nullptr);
18291 InscanCopyArrayTemps.push_back(
nullptr);
18292 InscanCopyArrayElems.push_back(
nullptr);
18297 Expr *TaskgroupDescriptor,
Expr *CopyOp,
Expr *CopyArrayTemp,
18298 Expr *CopyArrayElem) {
18299 Vars.emplace_back(Item);
18300 Privates.emplace_back(Private);
18301 LHSs.emplace_back(LHS);
18302 RHSs.emplace_back(RHS);
18303 ReductionOps.emplace_back(ReductionOp);
18304 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18305 if (RedModifier == OMPC_REDUCTION_inscan) {
18306 InscanCopyOps.push_back(CopyOp);
18307 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18308 InscanCopyArrayElems.push_back(CopyArrayElem);
18310 assert(CopyOp ==
nullptr && CopyArrayTemp ==
nullptr &&
18311 CopyArrayElem ==
nullptr &&
18312 "Copy operation must be used for inscan reductions only.");
18322 if (Length ==
nullptr) {
18329 SingleElement =
true;
18330 ArraySizes.push_back(llvm::APSInt::get(1));
18333 if (!Length->EvaluateAsInt(
Result, Context))
18336 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
18337 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18338 ArraySizes.push_back(ConstantLengthValue);
18346 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base)) {
18347 Length = TempOASE->getLength();
18348 if (Length ==
nullptr) {
18355 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18356 ArraySizes.push_back(ConstantOne);
18359 if (!Length->EvaluateAsInt(
Result, Context))
18362 llvm::APSInt ConstantLengthValue =
Result.Val.getInt();
18363 if (ConstantLengthValue.getSExtValue() != 1)
18366 ArraySizes.push_back(ConstantLengthValue);
18368 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18372 if (!SingleElement) {
18373 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base)) {
18375 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18376 ArraySizes.push_back(ConstantOne);
18377 Base = TempASE->getBase()->IgnoreParenImpCasts();
18389 return BO_AddAssign;
18391 return BO_MulAssign;
18393 return BO_AndAssign;
18395 return BO_OrAssign;
18397 return BO_XorAssign;
18453 case OO_Array_Delete:
18462 case OO_GreaterEqual:
18464 case OO_MinusEqual:
18466 case OO_SlashEqual:
18467 case OO_PercentEqual:
18468 case OO_CaretEqual:
18472 case OO_GreaterGreater:
18473 case OO_LessLessEqual:
18474 case OO_GreaterGreaterEqual:
18475 case OO_EqualEqual:
18476 case OO_ExclaimEqual:
18479 case OO_MinusMinus:
18485 case OO_Conditional:
18488 llvm_unreachable(
"Unexpected reduction identifier");
18491 if (II->isStr(
"max"))
18493 else if (II->isStr(
"min"))
18501 if (OOK == OO_Minus && S.
LangOpts.OpenMP == 52)
18502 S.
Diag(ReductionId.
getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18505 if (ReductionIdScopeSpec.
isValid())
18511 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18512 bool FirstIter =
true;
18513 for (
Expr *RefExpr : VarList) {
18514 assert(RefExpr &&
"nullptr expr in OpenMP reduction clause.");
18522 if (!FirstIter && IR != ER)
18527 Expr *SimpleRefExpr = RefExpr;
18536 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18537 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
18538 Expr *ReductionOp =
nullptr;
18540 (DeclareReductionRef.
isUnset() ||
18541 isa<UnresolvedLookupExpr>(DeclareReductionRef.
get())))
18542 ReductionOp = DeclareReductionRef.
get();
18544 RD.push(RefExpr, ReductionOp);
18550 Expr *TaskgroupDescriptor =
nullptr;
18552 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
18553 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
18555 Type = ASE->getType().getNonReferenceType();
18560 Type = ATy->getElementType();
18563 Type =
Type.getNonReferenceType();
18567 auto *VD = dyn_cast<VarDecl>(
D);
18573 diag::err_omp_reduction_incomplete_type))
18579 false, ASE || OASE))
18586 if (!ASE && !OASE) {
18588 VarDecl *VDDef = VD->getDefinition();
18590 DSARefChecker Check(Stack);
18591 if (Check.Visit(VDDef->
getInit())) {
18592 S.
Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
18593 << getOpenMPClauseName(ClauseKind) << ERange;
18611 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(
D,
false);
18612 if (DVar.CKind == OMPC_reduction) {
18613 S.
Diag(ELoc, diag::err_omp_once_referenced)
18614 << getOpenMPClauseName(ClauseKind);
18616 S.
Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
18619 if (DVar.CKind != OMPC_unknown) {
18620 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
18621 << getOpenMPClauseName(DVar.CKind)
18622 << getOpenMPClauseName(OMPC_reduction);
18634 DVar = Stack->getImplicitDSA(
D,
true);
18635 if (DVar.CKind != OMPC_shared) {
18636 S.
Diag(ELoc, diag::err_omp_required_access)
18637 << getOpenMPClauseName(OMPC_reduction)
18638 << getOpenMPClauseName(OMPC_shared);
18646 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(
D,
false);
18647 if (DVar.CKind == OMPC_threadprivate) {
18648 S.
Diag(ELoc, diag::err_omp_wrong_dsa)
18649 << getOpenMPClauseName(DVar.CKind)
18650 << getOpenMPClauseName(OMPC_reduction);
18660 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18661 ReductionId,
Type, BasePath, IR == ER ?
nullptr : *IR);
18665 (DeclareReductionRef.
isUnset() ||
18666 isa<UnresolvedLookupExpr>(DeclareReductionRef.
get()))) {
18667 RD.push(RefExpr, DeclareReductionRef.
get());
18670 if (BOK == BO_Comma && DeclareReductionRef.
isUnset()) {
18674 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
18675 <<
Type << ReductionIdRange;
18678 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
18679 <<
Type << ReductionIdRange;
18691 if (DeclareReductionRef.
isUnset()) {
18692 if ((BOK == BO_GT || BOK == BO_LT) &&
18695 S.
Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
18696 << getOpenMPClauseName(ClauseKind) << S.
getLangOpts().CPlusPlus;
18697 if (!ASE && !OASE) {
18698 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18701 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18706 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
18708 S.
Diag(ELoc, diag::err_omp_clause_floating_type_arg)
18709 << getOpenMPClauseName(ClauseKind);
18710 if (!ASE && !OASE) {
18711 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18714 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18721 Type =
Type.getNonLValueExprType(Context).getUnqualifiedType();
18730 bool ConstantLengthOASE =
false;
18732 bool SingleElement;
18735 Context, OASE, SingleElement, ArraySizes);
18738 if (ConstantLengthOASE && !SingleElement) {
18739 for (llvm::APSInt &Size : ArraySizes)
18746 if ((OASE && !ConstantLengthOASE) ||
18748 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
18751 S.
Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18752 S.
Diag(ELoc, diag::note_vla_unsupported);
18755 S.
targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18756 S.
targetDiag(ELoc, diag::note_vla_unsupported);
18769 }
else if (!ASE && !OASE &&
18771 PrivateTy =
D->getType().getNonReferenceType();
18777 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
18782 if (DeclareReductionRef.
isUsable()) {
18784 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
18785 if (DRD->getInitializer()) {
18811 Type = ComplexTy->getElementType();
18813 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
18820 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
18842 llvm::APInt InitValue =
18843 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
18844 : llvm::APInt::getMinValue(Size)
18845 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
18846 : llvm::APInt::getMaxValue(Size);
18857 llvm::APFloat InitValue = llvm::APFloat::getLargest(
18888 llvm_unreachable(
"Unexpected reduction operation");
18897 }
else if (!
Init) {
18907 S.
Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
18908 <<
Type << ReductionIdRange;
18909 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18912 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18918 if (DeclareReductionRef.
isUsable()) {
18923 if (!BasePath.empty()) {
18927 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.
get(), &BasePath,
18930 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.
get(), &BasePath,
18934 QualType Params[] = {PtrRedTy, PtrRedTy};
18949 CombBOK, LHSDRE, RHSDRE);
18956 if (BOK != BO_LT && BOK != BO_GT) {
18959 BO_Assign, LHSDRE, ReductionOp.
get());
18961 auto *ConditionalOp =
new (Context)
18966 BO_Assign, LHSDRE, ConditionalOp);
18979 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
18980 if (ClauseKind == OMPC_reduction &&
18981 RD.RedModifier == OMPC_REDUCTION_inscan) {
18983 CopyOpRes = S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
18993 if (Stack->getCurrentDirective() == OMPD_simd ||
19031 if (ClauseKind == OMPC_in_reduction) {
19034 const Expr *ParentReductionOp =
nullptr;
19035 Expr *ParentBOKTD =
nullptr, *ParentReductionOpTD =
nullptr;
19036 DSAStackTy::DSAVarData ParentBOKDSA =
19037 Stack->getTopMostTaskgroupReductionData(
D, ParentSR, ParentBOK,
19039 DSAStackTy::DSAVarData ParentReductionOpDSA =
19040 Stack->getTopMostTaskgroupReductionData(
19041 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19042 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19043 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19044 if ((DeclareReductionRef.
isUnset() && IsParentReductionOp) ||
19045 (DeclareReductionRef.
isUsable() && IsParentBOK) ||
19046 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19047 bool EmitError =
true;
19048 if (IsParentReductionOp && DeclareReductionRef.
isUsable()) {
19049 llvm::FoldingSetNodeID RedId, ParentRedId;
19050 ParentReductionOp->
Profile(ParentRedId, Context,
true);
19051 DeclareReductionRef.
get()->
Profile(RedId, Context,
19053 EmitError = RedId != ParentRedId;
19057 diag::err_omp_reduction_identifier_mismatch)
19058 << ReductionIdRange << RefExpr->getSourceRange();
19060 diag::note_omp_previous_reduction_identifier)
19062 << (IsParentBOK ? ParentBOKDSA.RefExpr
19063 : ParentReductionOpDSA.RefExpr)
19064 ->getSourceRange();
19068 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19075 TransformExprToCaptures RebuildToCapture(S,
D);
19077 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19078 Ref = RebuildToCapture.getCapturedExpr();
19083 RD.ExprCaptures.emplace_back(Ref->
getDecl());
19089 S.
BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
19094 Stack->getCurrentDirective() == OMPD_taskgroup) {
19095 S.
Diag(RefExpr->getExprLoc(),
19096 diag::err_omp_reduction_non_addressable_expression)
19097 << RefExpr->getSourceRange();
19100 RD.ExprPostUpdates.emplace_back(
19107 unsigned Modifier = RD.RedModifier;
19110 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19111 Modifier = OMPC_REDUCTION_task;
19112 Stack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19114 if (Modifier == OMPC_REDUCTION_task &&
19115 (CurrDir == OMPD_taskgroup ||
19119 if (DeclareReductionRef.
isUsable())
19120 Stack->addTaskgroupReductionData(
D, ReductionIdRange,
19121 DeclareReductionRef.
get());
19123 Stack->addTaskgroupReductionData(
D, ReductionIdRange, BOK);
19125 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.
get(),
19126 TaskgroupDescriptor, CopyOpRes.
get(), TempArrayRes.
get(),
19127 TempArrayElem.
get());
19129 return RD.Vars.empty();
19139 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19142 << getOpenMPClauseName(OMPC_reduction);
19150 if (Modifier == OMPC_REDUCTION_inscan &&
19151 (
DSAStack->getCurrentDirective() != OMPD_for &&
19152 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19153 DSAStack->getCurrentDirective() != OMPD_simd &&
19154 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19155 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19156 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19160 ReductionData RD(VarList.size(), Modifier);
19162 StartLoc, LParenLoc, ColonLoc, EndLoc,
19163 ReductionIdScopeSpec, ReductionId,
19164 UnresolvedReductions, RD))
19168 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
19171 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19172 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19182 ReductionData RD(VarList.size());
19184 VarList, StartLoc, LParenLoc, ColonLoc,
19185 EndLoc, ReductionIdScopeSpec, ReductionId,
19186 UnresolvedReductions, RD))
19190 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19192 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19202 ReductionData RD(VarList.size());
19204 StartLoc, LParenLoc, ColonLoc, EndLoc,
19205 ReductionIdScopeSpec, ReductionId,
19206 UnresolvedReductions, RD))
19210 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19212 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19221 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19231 const auto *VD = dyn_cast_or_null<VarDecl>(
D);
19234 diag::err_omp_linear_incomplete_type))
19236 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19238 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19242 Type =
Type.getNonReferenceType();
19249 if (!IsDeclareSimd &&
19254 Type =
Type.getUnqualifiedType().getCanonicalType();
19255 const auto *Ty =
Type.getTypePtrOrNull();
19256 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19257 !Ty->isIntegralType(
getASTContext()) && !Ty->isPointerType())) {
19258 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) <<
Type;
19260 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19263 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19286 Diag(Step->
getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
19288 LinKind = OMPC_LINEAR_val;
19289 for (
Expr *RefExpr : VarList) {
19290 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
19293 Expr *SimpleRefExpr = RefExpr;
19297 Vars.push_back(RefExpr);
19298 Privates.push_back(
nullptr);
19299 Inits.push_back(
nullptr);
19306 auto *VD = dyn_cast<VarDecl>(
D);
19312 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
19313 if (DVar.RefExpr) {
19314 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19315 << getOpenMPClauseName(OMPC_linear);
19322 Type =
Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19328 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
19337 ExprCaptures.push_back(Ref->
getDecl());
19344 SimpleRefExpr, RefRes.
get());
19347 ExprPostUpdates.push_back(
19352 if (LinKind == OMPC_LINEAR_uval)
19353 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19355 InitExpr = VD ? SimpleRefExpr : Ref;
19361 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19363 ? RefExpr->IgnoreParens()
19365 Privates.push_back(PrivateRef);
19366 Inits.push_back(InitRef);
19372 Expr *StepExpr = Step;
19373 Expr *CalcStepExpr =
nullptr;
19381 StepExpr = Val.
get();
19395 if (std::optional<llvm::APSInt>
Result =
19397 if (!
Result->isNegative() && !
Result->isStrictlyPositive())
19398 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19399 << Vars[0] << (Vars.size() > 1);
19403 CalcStepExpr = CalcStep.
get();
19408 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19409 Vars, Privates, Inits, StepExpr, CalcStepExpr,
19415 Expr *NumIterations,
Sema &SemaRef,
19416 Scope *S, DSAStackTy *Stack) {
19428 Step = cast<BinaryOperator>(CalcStep)->getLHS();
19429 bool HasErrors =
false;
19430 auto CurInit = Clause.
inits().begin();
19431 auto CurPrivate = Clause.
privates().begin();
19436 Expr *SimpleRefExpr = RefExpr;
19437 auto Res =
getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19439 if (Res.second || !
D) {
19440 Updates.push_back(
nullptr);
19441 Finals.push_back(
nullptr);
19445 auto &&Info = Stack->isLoopControlVariable(
D);
19452 diag::err_omp_linear_distribute_var_non_loop_iteration);
19453 Updates.push_back(
nullptr);
19454 Finals.push_back(
nullptr);
19458 Expr *InitExpr = *CurInit;
19461 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19463 if (LinKind == OMPC_LINEAR_uval)
19464 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19468 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19475 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19486 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19489 Final = *CurPrivate;
19493 if (!
Update.isUsable() || !Final.isUsable()) {
19494 Updates.push_back(
nullptr);
19495 Finals.push_back(
nullptr);
19496 UsedExprs.push_back(
nullptr);
19499 Updates.push_back(
Update.get());
19500 Finals.push_back(Final.get());
19502 UsedExprs.push_back(SimpleRefExpr);
19508 UsedExprs.push_back(S);
19510 UsedExprs.append(Clause.
varlist_size() + 1 - UsedExprs.size(),
nullptr);
19521 for (
Expr *RefExpr : VarList) {
19522 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
19525 Expr *SimpleRefExpr = RefExpr;
19529 Vars.push_back(RefExpr);
19536 auto *VD = dyn_cast<VarDecl>(
D);
19544 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
19546 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19549 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19556 if (
const Expr *PrevRef =
DSAStack->addUniqueAligned(
D, SimpleRefExpr)) {
19557 Diag(ELoc, diag::err_omp_used_in_clause_twice)
19558 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
19559 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
19560 << getOpenMPClauseName(OMPC_aligned);
19568 .DefaultFunctionArrayConversion(
19569 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
19578 if (Alignment !=
nullptr) {
19583 Alignment = AlignResult.
get();
19589 ColonLoc, EndLoc, Vars, Alignment);
19600 for (
Expr *RefExpr : VarList) {
19601 assert(RefExpr &&
"NULL expr in OpenMP copyin clause.");
19602 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19604 Vars.push_back(RefExpr);
19605 SrcExprs.push_back(
nullptr);
19606 DstExprs.push_back(
nullptr);
19607 AssignmentOps.push_back(
nullptr);
19616 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
19617 if (!DE || !isa<VarDecl>(DE->getDecl())) {
19618 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
19619 << 0 << RefExpr->getSourceRange();
19623 Decl *
D = DE->getDecl();
19624 auto *VD = cast<VarDecl>(
D);
19629 Vars.push_back(DE);
19630 SrcExprs.push_back(
nullptr);
19631 DstExprs.push_back(
nullptr);
19632 AssignmentOps.push_back(
nullptr);
19638 if (!
DSAStack->isThreadPrivate(VD)) {
19639 Diag(ELoc, diag::err_omp_required_access)
19640 << getOpenMPClauseName(OMPC_copyin)
19641 << getOpenMPDirectiveName(OMPD_threadprivate);
19665 PseudoDstExpr, PseudoSrcExpr);
19674 DSAStack->addDSA(VD, DE, OMPC_copyin);
19675 Vars.push_back(DE);
19676 SrcExprs.push_back(PseudoSrcExpr);
19677 DstExprs.push_back(PseudoDstExpr);
19678 AssignmentOps.push_back(AssignmentOp.
get());
19685 Vars, SrcExprs, DstExprs, AssignmentOps);
19696 for (
Expr *RefExpr : VarList) {
19697 assert(RefExpr &&
"NULL expr in OpenMP linear clause.");
19700 Expr *SimpleRefExpr = RefExpr;
19704 Vars.push_back(RefExpr);
19705 SrcExprs.push_back(
nullptr);
19706 DstExprs.push_back(
nullptr);
19707 AssignmentOps.push_back(
nullptr);
19714 auto *VD = dyn_cast<VarDecl>(
D);
19719 if (!VD || !
DSAStack->isThreadPrivate(VD)) {
19720 DSAStackTy::DSAVarData DVar =
19722 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
19724 Diag(ELoc, diag::err_omp_wrong_dsa)
19725 << getOpenMPClauseName(DVar.CKind)
19726 << getOpenMPClauseName(OMPC_copyprivate);
19734 if (DVar.CKind == OMPC_unknown) {
19735 DVar =
DSAStack->getImplicitDSA(
D,
false);
19736 if (DVar.CKind == OMPC_shared) {
19737 Diag(ELoc, diag::err_omp_required_access)
19738 << getOpenMPClauseName(OMPC_copyprivate)
19739 <<
"threadprivate or private in the enclosing context";
19748 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19749 << getOpenMPClauseName(OMPC_copyprivate) <<
Type
19750 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
19751 bool IsDecl = !VD || VD->isThisDeclarationADefinition(
getASTContext()) ==
19754 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19775 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
19787 VD ? RefExpr->IgnoreParens()
19789 SrcExprs.push_back(PseudoSrcExpr);
19790 DstExprs.push_back(PseudoDstExpr);
19791 AssignmentOps.push_back(AssignmentOp.
get());
19798 EndLoc, Vars, SrcExprs, DstExprs,
19806 if (VarList.empty())
19815 bool Diagnose =
true) {
19816 QualType OMPDependT = Stack->getOMPDependT();
19817 if (!OMPDependT.
isNull())
19823 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_depend_t";
19826 Stack->setOMPDependT(PT.
get());
19847 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19852 Diag(Depobj->
getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19862struct DoacrossDataInfoTy {
19868 llvm::APSInt TotalDepCount;
19871static DoacrossDataInfoTy
19878 llvm::APSInt DepCounter(32);
19879 llvm::APSInt TotalDepCount(32);
19881 if (
const Expr *OrderedCountExpr =
19882 Stack->getParentOrderedRegionParam().first) {
19883 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.
Context);
19884 TotalDepCount.setIsUnsigned(
true);
19887 for (
Expr *RefExpr : VarList) {
19888 assert(RefExpr &&
"NULL expr in OpenMP doacross clause.");
19889 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19891 Vars.push_back(RefExpr);
19898 if (Stack->getParentOrderedRegionParam().first &&
19899 DepCounter >= TotalDepCount) {
19900 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
19914 Vars.push_back(RefExpr);
19920 Expr *LHS = SimpleExpr;
19921 Expr *RHS =
nullptr;
19922 if (
auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
19924 OOLoc = BO->getOperatorLoc();
19927 }
else if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
19928 OOK = OCE->getOperator();
19929 OOLoc = OCE->getOperatorLoc();
19932 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
19933 OOK = MCE->getMethodDecl()
19936 .getCXXOverloadedOperator();
19937 OOLoc = MCE->getCallee()->getExprLoc();
19946 Vars.push_back(RefExpr);
19952 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK !=
OO_None)) {
19953 SemaRef.
Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
19959 RHS, OMPC_depend,
false);
19964 Stack->getParentOrderedRegionParam().first &&
19965 DepCounter != Stack->isParentLoopControlVariable(
D).first) {
19967 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
19969 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19972 SemaRef.
Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19976 OpsOffs.emplace_back(RHS, OOK);
19978 Vars.push_back(RefExpr->IgnoreParenImpCasts());
19981 TotalDepCount > VarList.size() &&
19982 Stack->getParentOrderedRegionParam().first &&
19983 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
19984 SemaRef.
Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
19985 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
19987 return {Vars, OpsOffs, TotalDepCount};
19996 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
19997 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
19998 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19999 <<
"'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
20002 if (
DSAStack->getCurrentDirective() == OMPD_taskwait &&
20003 DepKind == OMPC_DEPEND_mutexinoutset) {
20004 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20007 if ((
DSAStack->getCurrentDirective() != OMPD_ordered ||
20008 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20010 DepKind == OMPC_DEPEND_sink ||
20012 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20013 DepKind == OMPC_DEPEND_depobj))) {
20015 OMPC_DEPEND_outallmemory,
20016 OMPC_DEPEND_inoutallmemory};
20018 DSAStack->getCurrentDirective() == OMPD_depobj)
20019 Except.push_back(OMPC_DEPEND_depobj);
20021 Except.push_back(OMPC_DEPEND_inoutset);
20023 ?
"depend modifier(iterator) or "
20025 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20029 << getOpenMPClauseName(OMPC_depend);
20033 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20035 diag::err_omp_depend_sink_source_with_modifier);
20040 Diag(DepModifier->
getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20044 llvm::APSInt TotalDepCount(32);
20046 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20049 Vars = VarOffset.Vars;
20050 OpsOffs = VarOffset.OpsOffs;
20051 TotalDepCount = VarOffset.TotalDepCount;
20053 for (
Expr *RefExpr : VarList) {
20054 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
20055 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20057 Vars.push_back(RefExpr);
20063 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
20064 bool OMPDependTFound =
getLangOpts().OpenMP >= 50;
20065 if (OMPDependTFound)
20067 DepKind == OMPC_DEPEND_depobj);
20068 if (DepKind == OMPC_DEPEND_depobj) {
20072 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20073 !RefExpr->isInstantiationDependent() &&
20074 !RefExpr->containsUnexpandedParameterPack() &&
20075 (OMPDependTFound &&
20077 DSAStack->getOMPDependT(), RefExpr->getType()))) {
20078 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20079 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20082 if (!RefExpr->isLValue()) {
20083 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20084 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20091 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20092 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
20099 ExprTy = ATy->getElementType();
20105 const Expr *Length = OASE->getLength();
20107 if (Length && !Length->isValueDependent() &&
20109 Result.Val.getInt().isZero()) {
20111 diag::err_omp_depend_zero_length_array_section_not_allowed)
20121 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20122 !RefExpr->isInstantiationDependent() &&
20123 !RefExpr->containsUnexpandedParameterPack() &&
20124 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20125 (OMPDependTFound &&
DSAStack->getOMPDependT().getTypePtr() ==
20127 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20130 << RefExpr->getSourceRange();
20134 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
20135 if (ASE && !ASE->getBase()->isTypeDependent() &&
20138 .getNonReferenceType()
20139 ->isPointerType() &&
20140 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20141 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20144 << RefExpr->getSourceRange();
20152 RefExpr->IgnoreParenImpCasts());
20154 if (!Res.
isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
20155 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
20156 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20159 << RefExpr->getSourceRange();
20164 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20168 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20169 DepKind != OMPC_DEPEND_outallmemory &&
20170 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20175 {DepKind, DepLoc,
Data.ColonLoc,
Data.OmpAllMemoryLoc}, DepModifier, Vars,
20176 TotalDepCount.getZExtValue());
20177 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20178 DSAStack->isParentOrderedRegion())
20179 DSAStack->addDoacrossDependClause(
C, OpsOffs);
20188 "Unexpected device modifier in OpenMP < 50.");
20190 bool ErrorFound =
false;
20192 std::string Values =
20194 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20195 << Values << getOpenMPClauseName(OMPC_device);
20200 Stmt *HelperValStmt =
nullptr;
20213 if (Modifier == OMPC_DEVICE_ancestor) {
20217 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20225 if (CaptureRegion != OMPD_unknown &&
20228 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20229 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
20234 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20235 LParenLoc, ModifierLoc, EndLoc);
20240 bool FullCheck =
true) {
20245 SemaRef.
Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20255 const auto *OASE = dyn_cast<ArraySectionExpr>(
E);
20260 if (isa<ArraySubscriptExpr>(
E) ||
20261 (OASE && OASE->getColonLocFirst().isInvalid())) {
20262 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
20263 return ATy->getSExtSize() != 1;
20268 assert(OASE &&
"Expecting array section if not an array subscript.");
20269 const Expr *LowerBound = OASE->getLowerBound();
20270 const Expr *Length = OASE->getLength();
20279 llvm::APSInt ConstLowerBound =
Result.Val.getInt();
20280 if (ConstLowerBound.getSExtValue())
20295 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr());
20303 llvm::APSInt ConstLength =
Result.Val.getInt();
20304 return CATy->getSExtSize() != ConstLength.getSExtValue();
20313 const auto *OASE = dyn_cast<ArraySectionExpr>(
E);
20317 if (isa<ArraySubscriptExpr>(
E) ||
20318 (OASE && OASE->getColonLocFirst().isInvalid()))
20321 assert(OASE &&
"Expecting array section if not an array subscript.");
20322 const Expr *Length = OASE->getLength();
20328 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
20329 return ATy->getSExtSize() != 1;
20339 llvm::APSInt ConstLength =
Result.Val.getInt();
20340 return ConstLength.getSExtValue() != 1;
20379class MapBaseChecker final :
public StmtVisitor<MapBaseChecker, bool> {
20384 bool IsNonContiguous =
false;
20385 bool NoDiagnose =
false;
20386 const Expr *RelevantExpr =
nullptr;
20387 bool AllowUnitySizeArraySection =
true;
20388 bool AllowWholeSizeArraySection =
true;
20389 bool AllowAnotherPtr =
true;
20393 void emitErrorMsg() {
20395 if (SemaRef.getLangOpts().OpenMP < 50) {
20397 diag::err_omp_expected_named_var_member_or_array_expression)
20400 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20401 << getOpenMPClauseName(CKind) << ERange;
20407 if (!isa<VarDecl>(DRE->
getDecl())) {
20411 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20412 RelevantExpr = DRE;
20414 Components.emplace_back(DRE, DRE->
getDecl(), IsNonContiguous);
20422 if (isa<CXXThisExpr>(BaseE)) {
20423 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20432 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20448 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20468 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20472 return RelevantExpr || Visit(
E);
20482 AllowUnitySizeArraySection =
false;
20483 AllowWholeSizeArraySection =
false;
20486 Components.emplace_back(ME, FD, IsNonContiguous);
20487 return RelevantExpr || Visit(
E);
20495 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20499 return RelevantExpr || Visit(
E);
20506 AllowWholeSizeArraySection =
false;
20512 !Result.Val.getInt().isZero()) {
20514 diag::err_omp_invalid_map_this_expr);
20516 diag::note_omp_invalid_subscript_on_this_ptr_map);
20518 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20523 Components.emplace_back(AE,
nullptr, IsNonContiguous);
20525 return RelevantExpr || Visit(
E);
20531 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
20532 "Array sections cannot be implicitly mapped.");
20546 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20556 if (AllowWholeSizeArraySection) {
20563 if (NotWhole || IsPointer)
20564 AllowWholeSizeArraySection =
false;
20565 }
else if (DKind == OMPD_target_update &&
20566 SemaRef.getLangOpts().OpenMP >= 50) {
20567 if (IsPointer && !AllowAnotherPtr)
20568 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
20571 IsNonContiguous =
true;
20572 }
else if (AllowUnitySizeArraySection && NotUnity) {
20578 diag::err_array_section_does_not_specify_contiguous_storage)
20584 AllowAnotherPtr =
false;
20586 if (
const auto *TE = dyn_cast<CXXThisExpr>(
E)) {
20593 diag::err_omp_invalid_map_this_expr);
20595 diag::note_omp_invalid_length_on_this_ptr_mapping);
20599 SemaRef.getASTContext()) &&
20602 diag::err_omp_invalid_map_this_expr);
20604 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
20606 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20611 Components.emplace_back(OASE,
nullptr,
false);
20612 return RelevantExpr || Visit(
E);
20618 Components.emplace_back(
E,
nullptr, IsNonContiguous);
20620 return Visit(
Base->IgnoreParenImpCasts());
20624 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->
isLValue() ||
20629 if (!RelevantExpr) {
20631 Components.emplace_back(UO,
nullptr,
false);
20647 Components.emplace_back(BO,
nullptr,
false);
20650 "Either LHS or RHS have base decl inside");
20652 return RelevantExpr || Visit(LE);
20653 return RelevantExpr || Visit(RE);
20656 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20657 RelevantExpr = CTE;
20658 Components.emplace_back(CTE,
nullptr, IsNonContiguous);
20662 assert(!RelevantExpr &&
"RelevantExpr is expected to be nullptr");
20663 Components.emplace_back(COCE,
nullptr, IsNonContiguous);
20667 Expr *Source =
E->getSourceExpr();
20672 return Visit(Source);
20674 bool VisitStmt(
Stmt *) {
20678 const Expr *getFoundBase()
const {
return RelevantExpr; }
20679 explicit MapBaseChecker(
20683 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
20684 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
20698 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
20702 if (SemaRef.
getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
20703 (CKind == OMPC_to || CKind == OMPC_from)) {
20704 auto CI = CurComponents.rbegin();
20705 auto CE = CurComponents.rend();
20706 for (; CI != CE; ++CI) {
20708 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
20713 SemaRef.
Diag(ELoc, diag::err_array_section_does_not_specify_length)
20717 return Checker.getFoundBase();
20726 bool CurrentRegionOnly,
20737 assert(!CurComponents.empty() &&
"Map clause expression with no components!");
20738 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
20739 "Map clause expression with unexpected base!");
20742 bool IsEnclosedByDataEnvironmentExpr =
false;
20743 const Expr *EnclosingExpr =
nullptr;
20745 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
20746 VD, CurrentRegionOnly,
20747 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
20748 ERange, CKind, &EnclosingExpr,
20752 if (CKind == Kind && SemaRef.
LangOpts.OpenMP >= 50)
20754 assert(!StackComponents.empty() &&
20755 "Map clause expression with no components!");
20756 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
20757 "Map clause expression with unexpected base!");
20761 const Expr *RE = StackComponents.front().getAssociatedExpression();
20767 auto CI = CurComponents.rbegin();
20768 auto CE = CurComponents.rend();
20769 auto SI = StackComponents.rbegin();
20770 auto SE = StackComponents.rend();
20771 for (; CI != CE && SI != SE; ++CI, ++SI) {
20776 if (CurrentRegionOnly &&
20777 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
20778 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
20779 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
20780 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
20781 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
20782 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
20783 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
20784 diag::err_omp_multiple_array_items_in_map_clause)
20785 << CI->getAssociatedExpression()->getSourceRange();
20786 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
20787 diag::note_used_here)
20788 << SI->getAssociatedExpression()->getSourceRange();
20793 if (CI->getAssociatedExpression()->getStmtClass() !=
20794 SI->getAssociatedExpression()->getStmtClass())
20798 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
20804 for (; SI != SE; ++SI) {
20806 if (
const auto *ASE =
20807 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
20808 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
20809 }
else if (
const auto *OASE = dyn_cast<ArraySectionExpr>(
20810 SI->getAssociatedExpression())) {
20811 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20812 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
20813 }
else if (
const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
20814 SI->getAssociatedExpression())) {
20815 Type = OASE->getBase()->getType()->getPointeeType();
20819 SemaRef, SI->getAssociatedExpression(),
Type))
20829 if (CI == CE && SI == SE) {
20830 if (CurrentRegionOnly) {
20831 if (CKind == OMPC_map) {
20832 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20834 assert(CKind == OMPC_to || CKind == OMPC_from);
20835 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20844 IsEnclosedByDataEnvironmentExpr =
true;
20849 std::prev(CI)->getAssociatedDeclaration()->getType();
20851 std::prev(CI)->getAssociatedExpression()->getExprLoc();
20870 if (CI == CE || SI == SE) {
20873 diag::err_omp_pointer_mapped_along_with_derived_section)
20879 if (CI->getAssociatedExpression()->getStmtClass() !=
20880 SI->getAssociatedExpression()->getStmtClass() ||
20881 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
20882 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
20883 assert(CI != CE && SI != SE);
20884 SemaRef.
Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
20897 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
20898 if (CKind == OMPC_map) {
20899 if (CI != CE || SI != SE) {
20903 CI != CE ? CurComponents.begin() : StackComponents.begin();
20904 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
20906 while (It != End && !It->getAssociatedDeclaration())
20907 std::advance(It, 1);
20908 assert(It != End &&
20909 "Expected at least one component with the declaration.");
20910 if (It !=
Begin && It->getAssociatedDeclaration()
20912 .getCanonicalType()
20913 ->isAnyPointerType()) {
20914 IsEnclosedByDataEnvironmentExpr =
false;
20915 EnclosingExpr =
nullptr;
20919 SemaRef.
Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20921 assert(CKind == OMPC_to || CKind == OMPC_from);
20922 SemaRef.
Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20932 if (!CurrentRegionOnly && SI != SE)
20933 EnclosingExpr = RE;
20937 IsEnclosedByDataEnvironmentExpr |=
20938 (!CurrentRegionOnly && CI != CE && SI == SE);
20943 if (CurrentRegionOnly)
20957 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
20959 diag::err_omp_original_storage_is_shared_and_does_not_contain)
20975 Expr *UnresolvedMapper) {
20991 while (S && !S->isDeclScope(
D))
20992 S = S->getParent();
20994 S = S->getParent();
20995 Lookups.emplace_back();
20996 Lookups.back().append(Lookup.
begin(), Lookup.
end());
20999 }
else if (
auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
21003 auto *DMD = cast<OMPDeclareMapperDecl>(
D);
21004 assert(DMD &&
"Expect valid OMPDeclareMapperDecl during instantiation.");
21005 Lookups.back().addDecl(DMD);
21013 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
21014 return !D->isInvalidDecl() &&
21015 (D->getType()->isDependentType() ||
21016 D->getType()->isInstantiationDependentType() ||
21017 D->getType()->containsUnexpandedParameterPack());
21028 false, URS.
begin(), URS.
end(),
false,
21036 SemaRef.
Diag(
Loc, diag::err_omp_mapper_wrong_type);
21043 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21053 if (
auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21057 !
Type.isMoreQualifiedThan(
D->getType(),
21077 SemaRef.
Diag(
Loc, diag::err_omp_invalid_mapper)
21087struct MappableVarListInfo {
21102 VarComponents.reserve(VarList.size());
21103 VarBaseDeclarations.reserve(VarList.size());
21122 for (
auto *FD : RD->
fields()) {
21130 SExprs.push_back(BE);
21138 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
21141 Maps.push_back(MapClause);
21142 return MapperVarRef;
21146 DSAStackTy *Stack) {
21161 MapperId = DeclNames.getIdentifier(&Ctx.
Idents.
get(
"default"));
21163 BaseType, MapperId, Maps,
nullptr);
21169 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21173 DMD->setMapperVarRef(MapperVarRef);
21193 while (S && !S->isDeclScope(
D))
21194 S = S->getParent();
21196 S = S->getParent();
21197 Lookups.emplace_back();
21198 Lookups.back().append(Lookup.
begin(), Lookup.
end());
21204 filterLookupForUDReductionAndMapper<bool>(Lookups, [](
ValueDecl *
D) {
21205 return !D->isInvalidDecl() &&
21206 (D->getType()->isDependentType() ||
21207 D->getType()->isInstantiationDependentType() ||
21208 D->getType()->containsUnexpandedParameterPack());
21215 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
21225 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21238 bool IsAmbiguous = !Paths.isAmbiguous(
21254 {CanonType,
nullptr});
21255 llvm::DenseMap<const Type *, bool>
Visited;
21257 while (!Types.empty()) {
21258 auto [BaseType, CurFD] = Types.pop_back_val();
21259 while (ParentChain.back().second == 0)
21260 ParentChain.pop_back();
21261 --ParentChain.back().second;
21262 if (BaseType.isNull())
21265 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
21268 auto It =
Visited.find(BaseType.getTypePtr());
21278 DefaultMapperId, BaseType);
21279 It =
Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
21285 bool FirstIter =
true;
21295 ParentChain.emplace_back(CurFD, 1);
21297 ++ParentChain.back().second;
21299 Types.emplace_back(FieldTy, FD);
21318 bool IsMapTypeImplicit =
false,
bool NoDiagnose =
false) {
21320 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21321 "Unexpected clause kind with mappable expressions!");
21329 MapperId.
setName(DeclNames.getIdentifier(
21331 MapperId.
setLoc(StartLoc);
21335 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21336 bool UpdateUMIt =
false;
21337 Expr *UnresolvedMapper =
nullptr;
21339 bool HasHoldModifier =
21340 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21348 for (
Expr *RE : MVLI.VarList) {
21349 assert(RE &&
"Null expr in omp to/from/map clause");
21353 if (UpdateUMIt && UMIt != UMEnd) {
21357 "Expect the size of UnresolvedMappers to match with that of VarList");
21361 UnresolvedMapper = *UMIt;
21370 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21374 MVLI.UDMapperList.push_back(ER.
get());
21377 MVLI.ProcessedVarList.push_back(RE);
21386 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21389 SemaRef.
Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21402 DSAS->getCurrentDirective(), NoDiagnose);
21406 assert(!CurComponents.empty() &&
21407 "Invalid mappable expression information.");
21409 if (
const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21411 DSAS->addMappedClassesQualTypes(TE->getType());
21414 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21418 MVLI.UDMapperList.push_back(ER.
get());
21420 MVLI.ProcessedVarList.push_back(RE);
21421 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21422 MVLI.VarComponents.back().append(CurComponents.begin(),
21423 CurComponents.end());
21424 MVLI.VarBaseDeclarations.push_back(
nullptr);
21431 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21432 assert(CurDeclaration &&
"Null decl on map clause.");
21435 "Expecting components to have associated only canonical declarations.");
21437 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21438 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21440 assert((VD || FD) &&
"Only variables or fields are expected here!");
21447 if (VD && DSAS->isThreadPrivate(VD)) {
21450 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
21451 SemaRef.
Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21452 << getOpenMPClauseName(CKind);
21466 true, CurComponents, CKind))
21468 if (CKind == OMPC_map &&
21471 false, CurComponents, CKind))
21478 auto I = llvm::find_if(
21483 assert(I != CurComponents.end() &&
"Null decl on map clause.");
21486 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->
IgnoreParens());
21487 auto *OASE = dyn_cast<ArraySectionExpr>(VE->
IgnoreParens());
21488 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->
IgnoreParens());
21490 Type = ASE->getType().getNonReferenceType();
21495 Type = ATy->getElementType();
21498 Type =
Type.getNonReferenceType();
21499 }
else if (OAShE) {
21513 if (CKind == OMPC_map) {
21520 if (DKind == OMPD_target_enter_data &&
21521 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21523 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21524 << (IsMapTypeImplicit ? 1 : 0)
21526 << getOpenMPDirectiveName(DKind);
21535 if (DKind == OMPD_target_exit_data &&
21536 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21537 MapType == OMPC_MAP_delete || SemaRef.
getLangOpts().OpenMP >= 52)) {
21538 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21539 << (IsMapTypeImplicit ? 1 : 0)
21541 << getOpenMPDirectiveName(DKind);
21550 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21552 SemaRef.
Diag(StartLoc,
21553 diag::err_omp_invalid_map_type_modifier_for_directive)
21555 OMPC_MAP_MODIFIER_ompx_hold)
21556 << getOpenMPDirectiveName(DKind);
21564 if ((DKind == OMPD_target_data ||
21566 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21567 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21568 SemaRef.
Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21569 << (IsMapTypeImplicit ? 1 : 0)
21571 << getOpenMPDirectiveName(DKind);
21583 if (VD && ((SemaRef.
LangOpts.OpenMP <= 45 &&
21585 DKind == OMPD_target)) {
21586 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD,
false);
21588 SemaRef.
Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21589 << getOpenMPClauseName(DVar.CKind)
21590 << getOpenMPClauseName(OMPC_map)
21591 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21600 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21601 Type.getCanonicalType(), UnresolvedMapper);
21604 if (!ER.
get() && isa<ArraySectionExpr>(VE)) {
21612 ElemType = ATy->getElementType();
21622 MVLI.UDMapperList.push_back(ER.
get());
21625 MVLI.ProcessedVarList.push_back(RE);
21629 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
21635 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21636 MVLI.VarComponents.back().append(CurComponents.begin(),
21637 CurComponents.end());
21638 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ?
nullptr
21658 BuiltinType::OMPIterator))
21660 diag::err_omp_map_modifier_not_iterator);
21663 unsigned Count = 0;
21664 for (
unsigned I = 0,
E = MapTypeModifiers.size(); I <
E; ++I) {
21666 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
21667 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
21671 "Modifiers exceed the allowed number of map type modifiers");
21672 Modifiers[Count] = MapTypeModifiers[I];
21673 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
21677 MappableVarListInfo MVLI(VarList);
21679 MapperIdScopeSpec, MapperId, UnresolvedMappers,
21680 MapType, Modifiers, IsMapTypeImplicit,
21686 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
21687 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
21689 MapperId, MapType, IsMapTypeImplicit, MapLoc);
21697 if (ReductionType.
isNull())
21705 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
21710 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
21714 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
21718 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
21721 return ReductionType;
21727 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
21730 Decls.reserve(ReductionTypes.size());
21739 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21741 bool InCompoundScope =
true;
21742 if (S !=
nullptr) {
21751 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
21753 while (Filter.hasNext()) {
21754 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
21755 if (InCompoundScope) {
21756 UsedAsPrevious.try_emplace(PrevDecl,
false);
21758 UsedAsPrevious[
D] =
true;
21760 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21761 PrevDecl->getLocation();
21764 if (InCompoundScope) {
21765 for (
const auto &PrevData : UsedAsPrevious) {
21766 if (!PrevData.second) {
21767 PrevDRD = PrevData.first;
21772 }
else if (PrevDeclInScope !=
nullptr) {
21773 auto *PrevDRDInScope = PrevDRD =
21774 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
21776 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
21777 PrevDRDInScope->getLocation();
21778 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
21779 }
while (PrevDRDInScope !=
nullptr);
21781 for (
const auto &TyData : ReductionTypes) {
21782 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
21784 if (I != PreviousRedeclTypes.end()) {
21785 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
21787 Diag(I->second, diag::note_previous_definition);
21790 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
21792 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
21794 DRD->setAccess(AS);
21795 Decls.push_back(DRD);
21797 DRD->setInvalidDecl();
21807 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21822 QualType ReductionType = DRD->getType();
21839 if (S !=
nullptr) {
21843 DRD->addDecl(OmpInParm);
21844 DRD->addDecl(OmpOutParm);
21850 DRD->setCombinerData(InE, OutE);
21855 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21862 if (Combiner !=
nullptr)
21863 DRD->setCombiner(Combiner);
21865 DRD->setInvalidDecl();
21870 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21884 QualType ReductionType = DRD->getType();
21901 if (S !=
nullptr) {
21905 DRD->addDecl(OmpPrivParm);
21906 DRD->addDecl(OmpOrigParm);
21912 DRD->setInitializerData(OrigE, PrivE);
21913 return OmpPrivParm;
21918 auto *DRD = cast<OMPDeclareReductionDecl>(
D);
21927 }
else if (OmpPrivParm->
hasInit()) {
21928 DRD->setInitializer(OmpPrivParm->
getInit(),
21933 DRD->setInvalidDecl();
21939 for (
Decl *
D : DeclReductions.
get()) {
21948 return DeclReductions;
21955 if (
D.isInvalidType())
21968 assert(
ParsedType.isUsable() &&
"Expect usable parsed mapper type");
21971 assert(!MapperType.
isNull() &&
"Expect valid mapper type");
21976 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
21993 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21995 bool InCompoundScope =
true;
21996 if (S !=
nullptr) {
22005 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22007 while (Filter.hasNext()) {
22008 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22009 if (InCompoundScope) {
22010 UsedAsPrevious.try_emplace(PrevDecl,
false);
22012 UsedAsPrevious[
D] =
true;
22014 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22015 PrevDecl->getLocation();
22018 if (InCompoundScope) {
22019 for (
const auto &PrevData : UsedAsPrevious) {
22020 if (!PrevData.second) {
22021 PrevDMD = PrevData.first;
22026 }
else if (PrevDeclInScope) {
22027 auto *PrevDMDInScope = PrevDMD =
22028 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22030 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22031 PrevDMDInScope->getLocation();
22032 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22033 }
while (PrevDMDInScope !=
nullptr);
22037 if (I != PreviousRedeclTypes.end()) {
22038 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22039 << MapperType << Name;
22040 Diag(I->second, diag::note_previous_definition);
22048 ClausesWithImplicit);
22050 MapperType, VN, ClausesWithImplicit,
22056 DMD->setAccess(AS);
22058 DMD->setInvalidDecl();
22060 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22064 DMD->setMapperVarRef(MapperVarRef);
22085 if (
DSAStack->getDeclareMapperVarRef())
22090 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
22092 if (
const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22105 assert(
getLangOpts().OpenMP &&
"Expected OpenMP mode.");
22106 return cast<DeclRefExpr>(
DSAStack->getDeclareMapperVarRef())->getDecl();
22113 if (VarList.empty())
22116 for (
Expr *ValExpr : VarList) {
22129 LParenLoc, EndLoc, VarList,
22132 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22134 for (
Expr *ValExpr : VarList) {
22136 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22137 Vars.push_back(ValExpr);
22142 LParenLoc, EndLoc, Vars, PreInit);
22149 if (VarList.empty())
22152 for (
Expr *ValExpr : VarList) {
22165 StartLoc, LParenLoc, EndLoc, VarList,
22168 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22170 for (
Expr *ValExpr : VarList) {
22172 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22173 Vars.push_back(ValExpr);
22178 LParenLoc, EndLoc, Vars, PreInit);
22186 Stmt *HelperValStmt =
nullptr;
22192 ValExpr,
SemaRef, OMPC_priority,
22194 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22198 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22206 "Unexpected grainsize modifier in OpenMP < 51.");
22211 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22212 << Values << getOpenMPClauseName(OMPC_grainsize);
22216 Expr *ValExpr = Grainsize;
22217 Stmt *HelperValStmt =
nullptr;
22227 &CaptureRegion, &HelperValStmt))
22232 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22240 "Unexpected num_tasks modifier in OpenMP < 51.");
22245 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22246 << Values << getOpenMPClauseName(OMPC_num_tasks);
22250 Expr *ValExpr = NumTasks;
22251 Stmt *HelperValStmt =
nullptr;
22258 ValExpr,
SemaRef, OMPC_num_tasks,
22260 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22265 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22285 DSAStackTy *Stack) {
22286 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22287 if (!OMPEventHandleT.
isNull())
22292 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_event_handle_t";
22295 Stack->setOMPEventHandleT(PT.
get());
22316 auto *VD = dyn_cast_or_null<VarDecl>(Ref->
getDecl());
22326 <<
"omp_event_handle_t" << 1 << VD->
getType()
22333 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(VD,
false);
22334 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22337 << getOpenMPClauseName(DVar.CKind)
22338 << getOpenMPClauseName(OMPC_firstprivate);
22353 std::string Values;
22357 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22358 << Values << getOpenMPClauseName(OMPC_dist_schedule);
22361 Expr *ValExpr = ChunkSize;
22362 Stmt *HelperValStmt =
nullptr;
22373 ValExpr = Val.
get();
22378 if (std::optional<llvm::APSInt>
Result =
22380 if (
Result->isSigned() && !
Result->isStrictlyPositive()) {
22381 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22386 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22390 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22391 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
22399 Kind, ValExpr, HelperValStmt);
22407 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22408 Kind != OMPC_DEFAULTMAP_scalar) {
22412 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22414 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22418 OMPC_DEFAULTMAP_scalar);
22422 Diag(
Loc, diag::err_omp_unexpected_clause_value)
22423 <<
Value << getOpenMPClauseName(OMPC_defaultmap);
22430 if (!isDefaultmapKind || !isDefaultmapModifier) {
22432 ?
"'scalar', 'aggregate', 'pointer'"
22433 :
"'scalar', 'aggregate', 'pointer', 'all'";
22435 StringRef ModifierValue =
"'alloc', 'from', 'to', 'tofrom', "
22436 "'firstprivate', 'none', 'default'";
22437 if (!isDefaultmapKind && isDefaultmapModifier) {
22438 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22439 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22440 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
22441 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22442 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22444 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22445 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22446 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22447 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22450 StringRef ModifierValue =
22451 "'alloc', 'from', 'to', 'tofrom', "
22452 "'firstprivate', 'none', 'default', 'present'";
22453 if (!isDefaultmapKind && isDefaultmapModifier) {
22454 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22455 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22456 }
else if (isDefaultmapKind && !isDefaultmapModifier) {
22457 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22458 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22460 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22461 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22462 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22463 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22472 if (
DSAStack->checkDefaultmapCategory(Kind)) {
22473 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22479 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
22480 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
22481 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
22483 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
22496 !isa<CXXRecordDecl>(CurLexicalContext) &&
22497 !isa<ClassTemplateDecl>(CurLexicalContext) &&
22498 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
22499 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
22500 Diag(DTCI.
Loc, diag::err_omp_region_not_file_context);
22506 Diag(DTCI.
Loc, diag::warn_hip_omp_target_directives);
22508 DeclareTargetNesting.push_back(DTCI);
22514 assert(!DeclareTargetNesting.empty() &&
22515 "check isInOpenMPDeclareTargetContext() first!");
22516 return DeclareTargetNesting.pop_back_val();
22526 if (DeclareTargetNesting.empty())
22529 Diag(DTCI.
Loc, diag::warn_omp_unterminated_declare_target)
22530 << getOpenMPDirectiveName(DTCI.
Kind);
22545 VarOrFuncDeclFilterCCC CCC(
SemaRef);
22556 Diag(
Id.getLoc(), diag::err_undeclared_var_use) <<
Id.getName();
22561 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22562 !isa<FunctionTemplateDecl>(ND)) {
22563 Diag(
Id.getLoc(), diag::err_omp_invalid_target_decl) <<
Id.getName();
22572 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
22573 isa<FunctionTemplateDecl>(ND)) &&
22574 "Expected variable, function or function template.");
22576 if (
auto *VD = dyn_cast<VarDecl>(ND)) {
22578 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22579 !VD->isStaticDataMember()) {
22580 Diag(
Loc, diag::err_omp_declare_target_has_local_vars)
22589 Diag(
Loc, diag::warn_omp_declare_target_after_first_use);
22593 Diag(
Loc, diag::warn_hip_omp_target_directives);
22596 const unsigned Level = -1;
22598 auto *VD = cast<ValueDecl>(ND);
22599 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22600 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22601 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.
DT &&
22602 (*ActiveAttr)->getLevel() == Level) {
22603 Diag(
Loc, diag::err_omp_device_type_mismatch)
22604 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.
DT)
22605 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22606 (*ActiveAttr)->getDevType());
22609 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
22610 (*ActiveAttr)->getLevel() == Level) {
22611 Diag(
Loc, diag::err_omp_declare_target_to_and_link) << ND;
22615 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
22618 Expr *IndirectE =
nullptr;
22619 bool IsIndirect =
false;
22625 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22630 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22632 if (
auto *VD = dyn_cast<VarDecl>(ND);
22634 VD->hasGlobalStorage())
22640 if (!
D || !isa<VarDecl>(
D))
22642 auto *VD = cast<VarDecl>(
D);
22643 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy>
MapTy =
22644 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22645 if (SemaRef.
LangOpts.OpenMP >= 50 &&
22648 VD->hasGlobalStorage()) {
22649 if (!
MapTy || (*
MapTy != OMPDeclareTargetDeclAttr::MT_To &&
22650 *
MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
22657 diag::err_omp_lambda_capture_in_declare_target_not_to);
22658 SemaRef.
Diag(SL, diag::note_var_explicitly_captured_here)
22665 SemaRef.
Diag(VD->
getLocation(), diag::warn_omp_not_in_target_context);
22666 SemaRef.
Diag(SL, diag::note_used_here) << SR;
22670 Sema &SemaRef, DSAStackTy *Stack,
22672 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
22683 if (
auto *VD = dyn_cast<VarDecl>(
D)) {
22685 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22686 !VD->isStaticDataMember())
22690 if (
DSAStack->isThreadPrivate(VD)) {
22691 Diag(SL, diag::err_omp_threadprivate_in_target);
22696 if (
const auto *FTD = dyn_cast<FunctionTemplateDecl>(
D))
22697 D = FTD->getTemplatedDecl();
22698 if (
auto *FD = dyn_cast<FunctionDecl>(
D)) {
22699 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
22700 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
22701 if (IdLoc.
isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
22702 Diag(IdLoc, diag::err_omp_function_in_link_clause);
22707 if (
auto *VD = dyn_cast<ValueDecl>(
D)) {
22715 if (isa<VarDecl>(
D) || isa<FunctionDecl>(
D) ||
22716 isa<FunctionTemplateDecl>(
D)) {
22717 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22718 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22719 unsigned Level = DeclareTargetNesting.size();
22720 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
22723 Expr *IndirectE =
nullptr;
22724 bool IsIndirect =
false;
22730 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22732 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
22733 : OMPDeclareTargetDeclAttr::MT_To,
22734 DTCI.
DT, IndirectE, IsIndirect, Level,
22738 ML->DeclarationMarkedOpenMPDeclareTarget(
D, A);
22758 if (
auto *VD = dyn_cast<VarDecl>(
Node->getDecl())) {
22760 DeclVector.push_back(VD);
22765 for (
auto *Child : Ex->
children()) {
22774 A = TD->
getAttr<OMPDeclareTargetDeclAttr>();
22775 DeclVector.push_back(cast<VarDecl>(TD));
22776 while (!DeclVector.empty()) {
22777 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
22778 if (TargetVarDecl->
hasAttr<OMPDeclareTargetDeclAttr>() &&
22792 if (isa<VarDecl>(TargetDecl))
22807 unsigned Count = 0;
22808 for (
unsigned I = 0,
E = MotionModifiers.size(); I <
E; ++I) {
22810 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22811 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22815 "Modifiers exceed the allowed number of motion modifiers");
22816 Modifiers[Count] = MotionModifiers[I];
22817 ModifiersLoc[Count] = MotionModifiersLoc[I];
22821 MappableVarListInfo MVLI(VarList);
22823 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22824 if (MVLI.ProcessedVarList.empty())
22828 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22829 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22844 unsigned Count = 0;
22845 for (
unsigned I = 0,
E = MotionModifiers.size(); I <
E; ++I) {
22847 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22848 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22852 "Modifiers exceed the allowed number of motion modifiers");
22853 Modifiers[Count] = MotionModifiers[I];
22854 ModifiersLoc[Count] = MotionModifiersLoc[I];
22858 MappableVarListInfo MVLI(VarList);
22860 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22861 if (MVLI.ProcessedVarList.empty())
22865 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22866 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22873 MappableVarListInfo MVLI(VarList);
22877 for (
Expr *RefExpr : VarList) {
22878 assert(RefExpr &&
"NULL expr in OpenMP use_device_ptr clause.");
22881 Expr *SimpleRefExpr = RefExpr;
22885 MVLI.ProcessedVarList.push_back(RefExpr);
22886 PrivateCopies.push_back(
nullptr);
22887 Inits.push_back(
nullptr);
22894 Type =
Type.getNonReferenceType().getUnqualifiedType();
22896 auto *VD = dyn_cast<VarDecl>(
D);
22900 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
22901 << 0 << RefExpr->getSourceRange();
22909 VD ? cast<DeclRefExpr>(SimpleRefExpr) :
nullptr);
22910 if (VDPrivate->isInvalidDecl())
22915 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
22931 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22932 PrivateCopies.push_back(VDPrivateRefExpr);
22933 Inits.push_back(VDInitRefExpr);
22938 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22942 MVLI.VarBaseDeclarations.push_back(
D);
22943 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22944 MVLI.VarComponents.back().emplace_back(SimpleRefExpr,
D,
22948 if (MVLI.ProcessedVarList.empty())
22952 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
22953 MVLI.VarBaseDeclarations, MVLI.VarComponents);
22959 MappableVarListInfo MVLI(VarList);
22961 for (
Expr *RefExpr : VarList) {
22962 assert(RefExpr &&
"NULL expr in OpenMP use_device_addr clause.");
22965 Expr *SimpleRefExpr = RefExpr;
22970 MVLI.ProcessedVarList.push_back(RefExpr);
22975 auto *VD = dyn_cast<VarDecl>(
D);
22982 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22987 DSAStack->addDSA(
D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22991 MVLI.VarBaseDeclarations.push_back(
D);
22992 MVLI.VarComponents.emplace_back();
22993 Expr *Component = SimpleRefExpr;
22994 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22995 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22998 MVLI.VarComponents.back().emplace_back(Component,
D,
23002 if (MVLI.ProcessedVarList.empty())
23006 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23007 MVLI.VarComponents);
23013 MappableVarListInfo MVLI(VarList);
23014 for (
Expr *RefExpr : VarList) {
23015 assert(RefExpr &&
"NULL expr in OpenMP is_device_ptr clause.");
23018 Expr *SimpleRefExpr = RefExpr;
23022 MVLI.ProcessedVarList.push_back(RefExpr);
23032 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23033 << 0 << RefExpr->getSourceRange();
23039 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
23041 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23042 << getOpenMPClauseName(DVar.CKind)
23043 << getOpenMPClauseName(OMPC_is_device_ptr)
23044 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
23049 const Expr *ConflictExpr;
23050 if (
DSAStack->checkMappableExprComponentListsForDecl(
23055 ConflictExpr = R.front().getAssociatedExpression();
23058 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23067 SimpleRefExpr,
D,
false);
23068 DSAStack->addMappableExpressionComponents(
23069 D, MC, OMPC_is_device_ptr);
23072 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23077 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23078 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23079 "Unexpected device pointer expression!");
23080 MVLI.VarBaseDeclarations.push_back(
23081 isa<DeclRefExpr>(SimpleRefExpr) ?
D :
nullptr);
23082 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23083 MVLI.VarComponents.back().push_back(MC);
23086 if (MVLI.ProcessedVarList.empty())
23090 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23091 MVLI.VarComponents);
23097 MappableVarListInfo MVLI(VarList);
23098 for (
Expr *RefExpr : VarList) {
23099 assert(RefExpr &&
"NULL expr in OpenMP has_device_addr clause.");
23102 Expr *SimpleRefExpr = RefExpr;
23107 MVLI.ProcessedVarList.push_back(RefExpr);
23115 DSAStackTy::DSAVarData DVar =
DSAStack->getTopDSA(
D,
false);
23117 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23118 << getOpenMPClauseName(DVar.CKind)
23119 << getOpenMPClauseName(OMPC_has_device_addr)
23120 << getOpenMPDirectiveName(
DSAStack->getCurrentDirective());
23125 const Expr *ConflictExpr;
23126 if (
DSAStack->checkMappableExprComponentListsForDecl(
23131 ConflictExpr = R.front().getAssociatedExpression();
23134 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23142 Expr *Component = SimpleRefExpr;
23143 auto *VD = dyn_cast<VarDecl>(
D);
23144 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23145 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23149 Component,
D,
false);
23150 DSAStack->addMappableExpressionComponents(
23151 D, MC, OMPC_has_device_addr);
23157 assert(Ref &&
"has_device_addr capture failed");
23158 MVLI.ProcessedVarList.push_back(Ref);
23160 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23165 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23166 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23167 "Unexpected device pointer expression!");
23168 MVLI.VarBaseDeclarations.push_back(
23169 isa<DeclRefExpr>(SimpleRefExpr) ?
D :
nullptr);
23170 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23171 MVLI.VarComponents.back().push_back(MC);
23174 if (MVLI.ProcessedVarList.empty())
23178 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23179 MVLI.VarComponents);
23193 bool AllocDependent =
23194 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
23195 Allocator->isInstantiationDependent() ||
23196 Allocator->containsUnexpandedParameterPack());
23197 if (!AllocDependent) {
23207 AllocatorRes.
get(),
DSAStack->getOMPAllocatorHandleT(),
23212 Allocator = AllocatorRes.
isUsable() ? AllocatorRes.
get() :
nullptr;
23229 if (!AlignmentDependent) {
23232 Alignment = AlignResult.
isUsable() ? AlignResult.
get() :
nullptr;
23237 for (
Expr *RefExpr : VarList) {
23238 assert(RefExpr &&
"NULL expr in OpenMP private clause.");
23241 Expr *SimpleRefExpr = RefExpr;
23245 Vars.push_back(RefExpr);
23251 auto *VD = dyn_cast<VarDecl>(
D);
23256 ? RefExpr->IgnoreParens()
23264 DSAStack->addInnerAllocatorExpr(Allocator);
23267 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
23268 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
23269 SecondAllocateModifierLoc, EndLoc, Vars);
23277 for (
Expr *RefExpr : VarList) {
23278 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
23281 Expr *SimpleRefExpr = RefExpr;
23285 Vars.push_back(RefExpr);
23292 if (
const Expr *PrevRef =
23293 DSAStack->addUniqueNontemporal(
D, SimpleRefExpr)) {
23294 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23295 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23296 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23297 << getOpenMPClauseName(OMPC_nontemporal);
23301 Vars.push_back(RefExpr);
23329 for (
Expr *RefExpr : VarList) {
23330 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
23333 Expr *SimpleRefExpr = RefExpr;
23338 Vars.push_back(RefExpr);
23343 const DSAStackTy::DSAVarData DVar =
23349 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23350 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23351 << RefExpr->getSourceRange();
23353 if (
DSAStack->getParentDirective() != OMPD_unknown)
23354 DSAStack->markDeclAsUsedInScanDirective(
D);
23355 Vars.push_back(RefExpr);
23370 for (
Expr *RefExpr : VarList) {
23371 assert(RefExpr &&
"NULL expr in OpenMP nontemporal clause.");
23374 Expr *SimpleRefExpr = RefExpr;
23379 Vars.push_back(RefExpr);
23385 DSAStackTy::DSAVarData DVar;
23386 if (ParentDirective != OMPD_unknown)
23392 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23393 DVar.Modifier != OMPC_REDUCTION_inscan) {
23394 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23395 << RefExpr->getSourceRange();
23397 DSAStack->markDeclAsUsedInScanDirective(
D);
23399 Vars.push_back(RefExpr);
23411 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23412 if (!OMPAlloctraitT.
isNull())
23417 S.
Diag(
Loc, diag::err_omp_implied_type_not_found) <<
"omp_alloctrait_t";
23420 Stack->setOMPAlloctraitT(PT.
get());
23440 for (
int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23441 auto AllocatorKind =
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy
>(I);
23442 StringRef Allocator =
23443 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23451 Expr *AllocatorExpr =
nullptr;
23453 if (
D.Allocator->isTypeDependent()) {
23454 AllocatorExpr =
D.Allocator;
23458 AllocatorExpr =
D.Allocator->IgnoreParenImpCasts();
23459 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
23460 bool IsPredefinedAllocator =
false;
23462 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
23464 IsPredefinedAllocator =
23466 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
23470 bool IsTypeCompatible = IsPredefinedAllocator;
23471 IsTypeCompatible = IsTypeCompatible ||
23473 OMPAllocatorHandleT);
23475 IsTypeCompatible ||
23477 bool IsNonConstantLValue =
23479 if (!DRE || !IsTypeCompatible ||
23480 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
23481 Diag(
D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23482 <<
"omp_allocator_handle_t" << (DRE ? 1 : 0)
23489 if (IsPredefinedAllocator &&
D.AllocatorTraits) {
23490 Diag(
D.AllocatorTraits->getExprLoc(),
23491 diag::err_omp_predefined_allocator_with_traits)
23493 Diag(
D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23494 << cast<NamedDecl>(DRE->
getDecl())->getName()
23501 if (!IsPredefinedAllocator && !
D.AllocatorTraits) {
23502 Diag(
D.Allocator->getExprLoc(),
23503 diag::err_omp_nonpredefined_allocator_without_traits);
23507 if (!
D.AllocatorTraits)
23511 IsPredefinedAllocator
23512 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
23513 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
23515 Expr *AllocatorTraitsExpr =
nullptr;
23516 if (
D.AllocatorTraits) {
23517 if (
D.AllocatorTraits->isTypeDependent()) {
23518 AllocatorTraitsExpr =
D.AllocatorTraits;
23524 AllocatorTraitsExpr =
D.AllocatorTraits->IgnoreParenImpCasts();
23529 if (
const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
23530 TraitTy = ConstArrayTy->getElementType();
23536 Diag(
D.AllocatorTraits->getExprLoc(),
23537 diag::err_omp_expected_array_alloctraits)
23538 << AllocatorTraitsExpr->
getType();
23543 if (
auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
23546 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
23563 for (
Expr *RefExpr : Locators) {
23564 assert(RefExpr &&
"NULL expr in OpenMP shared clause.");
23565 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23567 Vars.push_back(RefExpr);
23575 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23576 << 1 << 0 << RefExpr->getSourceRange();
23585 if (!Res.
isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
23586 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23587 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23588 << 1 << 0 << RefExpr->getSourceRange();
23591 Vars.push_back(SimpleExpr);
23595 ColonLoc, EndLoc, Modifier, Vars);
23604 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23607 << getOpenMPClauseName(OMPC_bind);
23612 LParenLoc, EndLoc);
23619 Expr *ValExpr = Size;
23620 Stmt *HelperValStmt =
nullptr;
23631 DKind, OMPC_ompx_dyn_cgroup_mem,
getLangOpts().OpenMP);
23632 if (CaptureRegion != OMPD_unknown &&
23635 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23636 ValExpr = tryBuildCapture(
SemaRef, ValExpr, Captures).get();
23641 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23649 if (
DSAStack->getCurrentDirective() == OMPD_ordered &&
23650 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
23651 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
23652 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
23653 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
23654 <<
"'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
23660 llvm::APSInt TotalDepCount(32);
23663 DepType == OMPC_DOACROSS_source ||
23664 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
23665 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
23667 Vars = VarOffset.Vars;
23668 OpsOffs = VarOffset.OpsOffs;
23669 TotalDepCount = VarOffset.TotalDepCount;
23671 EndLoc, DepType, DepLoc, ColonLoc, Vars,
23672 TotalDepCount.getZExtValue());
23673 if (
DSAStack->isParentOrderedRegion())
23674 DSAStack->addDoacrossDependClause(
C, OpsOffs);
23703 case OMPC_contains:
23706 llvm_unreachable(
"Unexpected OpenMP clause");
23714 case OMPC_no_openmp:
23716 case OMPC_no_openmp_routines:
23718 case OMPC_no_parallelism:
23721 llvm_unreachable(
"Unexpected OpenMP clause");
23730 if (
Base->hasPlaceholderType() &&
23731 !
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23744 LowerBound =
Result.get();
23746 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
23766 if (
Base->isTypeDependent() ||
23769 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
23773 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23785 Diag(
Base->getExprLoc(), diag::err_omp_typecheck_section_value)
23786 <<
Base->getSourceRange());
23792 if (Res.isInvalid())
23794 diag::err_omp_typecheck_section_not_integer)
23796 LowerBound = Res.get();
23806 if (Res.isInvalid())
23808 diag::err_omp_typecheck_section_not_integer)
23809 << 1 << Length->getSourceRange());
23810 Length = Res.get();
23812 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23813 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23814 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
23815 << 1 << Length->getSourceRange();
23822 diag::err_omp_typecheck_section_not_integer)
23824 Stride = Res.
get();
23837 Diag(
Base->getExprLoc(), diag::err_omp_section_function_type)
23838 << ResultTy <<
Base->getSourceRange();
23843 diag::err_omp_section_incomplete_type,
Base))
23851 llvm::APSInt LowerBoundValue =
Result.Val.getInt();
23852 if (LowerBoundValue.isNegative()) {
23854 diag::err_omp_section_not_subset_of_array)
23863 if (Length->EvaluateAsInt(
Result, Context)) {
23866 llvm::APSInt LengthValue =
Result.Val.getInt();
23867 if (LengthValue.isNegative()) {
23868 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
23869 <<
toString(LengthValue, 10,
true)
23870 << Length->getSourceRange();
23874 }
else if (ColonLocFirst.
isValid() &&
23880 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
23890 llvm::APSInt StrideValue =
Result.Val.getInt();
23891 if (!StrideValue.isStrictlyPositive()) {
23892 Diag(Stride->
getExprLoc(), diag::err_omp_section_stride_non_positive)
23893 <<
toString(StrideValue, 10,
true)
23900 if (!
Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23908 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23915 if (
Base->hasPlaceholderType()) {
23929 LParenLoc, RParenLoc, Dims, Brackets);
23931 (!
Base->isTypeDependent() &&
23934 diag::err_omp_non_pointer_type_array_shaping_base)
23935 <<
Base->getSourceRange());
23938 bool ErrorFound =
false;
23940 if (
Dim->hasPlaceholderType()) {
23942 if (
Result.isInvalid()) {
23947 if (
Result.isInvalid()) {
23953 if (!
Dim->isTypeDependent()) {
23956 if (
Result.isInvalid()) {
23958 Diag(
Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
23959 <<
Dim->getSourceRange();
23964 if (!
Dim->isValueDependent() &&
Dim->EvaluateAsInt(EvResult, Context)) {
23969 if (!
Value.isStrictlyPositive()) {
23970 Diag(
Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
23972 <<
Dim->getSourceRange();
23978 NewDims.push_back(
Dim);
23983 LParenLoc, RParenLoc, NewDims, Brackets);
23993 bool IsCorrect =
true;
23998 if (!
D.Type.getAsOpaquePtr()) {
24002 DeclTy = Context.
IntTy;
24003 StartLoc =
D.DeclIdentLoc;
24009 bool IsDeclTyDependent = DeclTy->isDependentType() ||
24010 DeclTy->containsUnexpandedParameterPack() ||
24011 DeclTy->isInstantiationDependentType();
24012 if (!IsDeclTyDependent) {
24013 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
24016 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24021 if (DeclTy.isConstant(Context)) {
24024 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24032 assert(
D.DeclIdent &&
"Identifier expected.");
24037 D.DeclIdent, DeclTy, TInfo,
SC_None);
24043 RedeclarationKind::ForVisibleRedeclaration);
24065 if (!IsDeclTyDependent &&
Begin && !
Begin->isTypeDependent()) {
24070 Expr *End =
D.Range.End;
24071 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
24074 End = EndRes.
get();
24076 Expr *Step =
D.Range.Step;
24079 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_not_integral)
24084 std::optional<llvm::APSInt>
Result =
24090 Diag(Step->
getExprLoc(), diag::err_omp_iterator_step_constant_zero)
24096 if (!
Begin || !End || !IsCorrect) {
24112 if (
Decl *ID =
D.IteratorDecl)
24113 ID->setInvalidDecl();
24125 D.Range.End,
D.Range.Begin);
24131 if (
D.Range.Step) {
24142 D.AssignmentLoc, BO_Sub, Res.
get(),
24159 D.AssignmentLoc, BO_Sub,
D.Range.Begin,
D.Range.End);
24173 D.AssignmentLoc, BO_Sub, Res1.
get(),
24188 D.AssignmentLoc, BO_GT,
D.Range.Step,
24213 CounterVD->setImplicit();
24220 if (
D.Range.Step) {
24222 D.AssignmentLoc, BO_Mul,
24232 D.Range.Begin, UpdateRes.
get());
24239 cast<VarDecl>(
D.IteratorDecl)->getType(),
24242 VDRes.
get(), UpdateRes.
get());
24254 D.AssignmentLoc, UO_PreInc, RefRes.
get());
24255 if (!CounterUpdateRes.
isUsable()) {
24261 if (!CounterUpdateRes.
isUsable()) {
24272 Helpers.assign(ID.size(), {});
24277 if (
Decl *ID =
D.IteratorDecl)
24278 ID->setInvalidDecl();
24283 LLoc, RLoc, ID, Helpers);
24288 StringRef AssumptionStr) {
24289 if (llvm::KnownAssumptionStrings.count(AssumptionStr))
24292 unsigned BestEditDistance = 3;
24293 StringRef Suggestion;
24294 for (
const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
24295 unsigned EditDistance =
24296 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
24297 if (EditDistance < BestEditDistance) {
24298 Suggestion = KnownAssumptionIt.getKey();
24299 BestEditDistance = EditDistance;
24303 if (!Suggestion.empty())
24304 S.
Diag(
Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
24305 << AssumptionStr << Suggestion;
24307 S.
Diag(
Loc, diag::warn_omp_assume_attribute_string_unknown)
24324 :
SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
enum clang::sema::@1724::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, Expr *Alignment, SourceLocation ColonLoc, OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc, OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
This represents 'allocator' clause in the '#pragma omp ...' directive.
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)
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.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, Expr *Alignment, OpenMPAllocateClauseModifier FirstModifier, SourceLocation FirstModifierLoc, OpenMPAllocateClauseModifier SecondModifier, SourceLocation SecondModifierLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
std::pair< StringRef, QualType > CapturedParamNameType
OMPClause * ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'final' clause.
bool isInOpenMPTargetExecutionDirective() const
Return true inside OpenMP target region.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target data' after parsing of the associated statement.
StmtResult ActOnOpenMPMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop' after parsing of the associated statement.
void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, SmallVectorImpl< FunctionDecl * > &Bases)
The declarator D defines a function in the scope S which is nested in an omp begin/end declare varian...
StmtResult ActOnOpenMPFlushDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp flush'.
StmtResult ActOnOpenMPUnrollDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp unroll' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPMapClause(Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapTypeModifiers, ArrayRef< SourceLocation > MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, bool NoDiagnose=false, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'map' clause.
OMPClause * ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_tasks' clause.
void ActOnOpenMPDeclareTargetInitializer(Decl *D)
Adds OMPDeclareTargetDeclAttr to referenced variables in declare target directive.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancellation point'.
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
void startOpenMPLoop()
If the current region is a loop-based region, mark the start of the loop construct.
StmtResult ActOnOpenMPTargetDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target' after parsing of the associated statement.
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
OMPThreadPrivateDecl * CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPThreadPrivateDecl and checks its correctness.
void handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL)
OMPClause * ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'severity' clause.
void 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.